wcscat_sが使えない

[戻る]
コイ 2012/12/28(金) 11:37:33
Visual Studio 2010を使っている者です。OSはwin7です。

win32プロジェクトにおいて、

wchar_t stringA[3]=L"";
wchar_t stringB[3]=L"AA";    
wcscat_s(stringA,stringB);

と記述したところ、コンパイルはエラーも警告もなく通るのですが、実行すると

「wcscat_sの0xfefefefeでハンドルされていない例外が発生しました:
0xC0000005:Access violation」

というウインドウが現れ、この中の中断を選ぶと逆アセンブルというウインドウが現れ
FEFEFEFE  ???というところに黄色い矢印が示されていました。

wcscat_sの正しい使い方は、どのようなものでしょうか。

お忙しいとは存じますが、宜しくお願いします。

コイ 2012/12/28(金) 11:52:47
すみません。
ビルド時の警告ありました。

warning C4996:This function or variable may be unsafe.Consider using 
wcscat_s_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See 
onlie help for details.
'wcscat_s' の宣言を確認してください。

しかし、http://msdn.microsoft.com/ja-jp/library/d45bbxx4(v=vs.100).aspxを読むと
wcscat_sの引数はwchar_t*型が2つなのですが、私は何か誤解しているのでしょうか。

tetrapod 2012/12/28(金) 12:23:06
提示例では
「元文字列用のバッファは結合後の文字列を保持するだけの大きさが必要」
という制約は満たしているので(ちょっと修正するとすぐバグりそうだが)
エラー無くコンパイルできて期待通り実行できるはず。
とりあえず「提示コードの範囲では」 wcscat_s を正しく使えているよ。

なのだが・・・警告メッセージが変。

wcscat の安全版が wcscat_s である。
wcscat_s を更に安全にした wcscat_s_s なんてものは俺の知っている範囲では無い。
# google 様も知らないようなのでたぶん全世界的に存在しないはず。

ということで
#define かなにかで wcscat を置き換えているコードがあるはず(提示ない箇所で)
まずはその辺を確認してみよう。

検証のためには新規 WIN32 コンソールアプリプロジェクトを作ってみるとか・・・

コイ 2012/12/28(金) 18:58:47
[[解決]]
ご返答、ありがとうございます。

コンソールアプリを作り、main内に

wchar_t stringA[3]=L"";
wchar_t stringB[3]=L"AA";    
wcscat_s(stringA,stringB);
std::wcout << stringA<<std::endl;

と記述したところ、無事にAAが出力されました。
次に、wcscat_sを選択し、「定義へ移動」したところ、wchar.hというファイルの980行
目の

__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_1(errno_t, wcscat_s, wchar_t, _Dest, 
_In_z_ const wchar_t *, _Source)

という箇所が指されました。

ただ、これからどうするか、わかりません。
引数がやはり2つだけということは分かり、色々調べたところwcsncat_sという変数もあ
るので、これを代用しようかと考えております。

tetrapod 2012/12/28(金) 21:56:28
wcscat_s には複数のバージョンがある。自分で示した MSDN ページにあるように
1.引数3個のもの errno_t wcscat_s(wchar_t* d, size_t n, const wchar_t* s);
2.引数2つ+暗黙の template 引数1個のもの
template<size_t n> errno_t wcscat_s(wchar_t (&d)[n], const wchar_t* s);

提示例では引数2つの wcscat_s を呼び出しているわけだ (template 版) 。
stringA が配列名だから、この配列名から要素数3を引き出すことが可能で、
wcscat_s(stringA, 3, stringB); と最終的には引数3つ版に変換されている。

C4996 は [引数が違う] という警告ではない。
C/C++ の言語仕様書にある一部の [不安全性の残る標準関数] を使うのを避けて
Microsoft 固有で用意した [より安全な独自関数] を使うといいよ、という警告。
# Microsoft 固有なので他社コンパイラに移植できなくなるけど...

提示ソース断片には何の問題も無いので
> これを代用しようかと考えております
勝手に違う関数を代用しないで、おかしくなっている真の原因を追究すべし。

古いスレッドには追加発言できません。