VS2005 で strcpy() を使おうとすると、「warning C4996: 'strcpy' が古い形式として宣言されました。」というメッセージが表示されるので、strcpy() を strcpy_s() に変更する訳ですが、strcpy_s() の戻り値である error_t のエラーをチェックしてる人っているんでしょうか?
strcpy_s() の使用者はあくまで strcpy() としての機能が欲しいのであり、それで警告が出るから仕方なく strcpy_s() にしているだけなのです。
?
でも、いざというときに error_t がエラーを返してきたらどうしよう、ということも考えてしまうわけです。
だからといって error_t をチェックしてどうこうなんて、めんどくさくてやってられません。
そこで考えつくのが error_t を例外にして投げるラッパーを作ってやることです。
inline void strcpy_s_ex(
char* strDestination,
size_t numberOfElements,
const char* strSource)
{
error_t e = ::strcpy_s(strDestination, numberOfElements, strSource);
if (e != 0)
{
throw e;
}
}
こうすることによって、わざわざエラーチェックをする必要が無くなり、例外をどこかでハンドリングしてやれば大丈夫ということになります。
少なくとも error_t のチェックを行わないよりは信頼性が上がるでしょう。
?
で、これを全ての関数について定義していくのは結構骨の折れる作業なのですが、実は ATL の一部である atlchecked.h に、strcpy_s() 等の error_t を返す関数を例外に変換するラッパーが定義されています。
namespace ATL
{
inline errno_t AtlCrtErrorCheck(errno_t nError)
{
switch(nError)
{
case ENOMEM:
AtlThrow(E_OUTOFMEMORY);
break;
case EINVAL:
case ERANGE:
AtlThrow(E_INVALIDARG);
break;
case 0:
case STRUNCATE:
break;
default:
AtlThrow(E_FAIL);
break;
}
return nError;
}
namespace Checked
{
inline void __cdecl strcpy_s(
__out_ecount(_S1max) char *_S1,
__in size_t _S1max,
__in_z const char *_S2)
{
AtlCrtErrorCheck(::strcpy_s(_S1, _S1max, _S2));
}
inline void __cdecl wcscpy_s(...)
{
...
}
...
}
}
ATL::Checked ネームスペースの下に、同名の関数が定義されています。
どうせ error_t のチェックなんて行わないのですから、こちらを使った方が良いかと思われます。
?
以上、ATL には意外に便利な関数がありますよーというお話でした。