Search
Categories
Articles
Rainmeter関連
ファイル置き場
お知り合いなど

スポンサーサイト

--.--.-- | スポンサー広告

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

WideCharToMultiByteにはまる

2009.04.25 | Programming

0 Comments

Rainmeterのプラグインを作っていて、挙動チェックにMeasureCalcを通したところ、出力される値がむちゃくちゃ……。
書式はあっているのに、1と出るはずのところで0しか出なかったり、ちゃんと出たり。数式をいじるとまたバグったり。プラグインのほうに問題があるのかと思い、チェックしてみるけれどわからず。

そういやCalcってログでるよなーと思い、ログを出力してみると……書式に指定したMeasure名が、たとえば「MeasureA」と指定しているのに「MeasureAT」とか、本来のものにゴミがついた状態で認識されて出力されているではないですか。さらに書式ミス時のエラーメッセージにも数文字分ゴミがついて出力されている……。本家版のRainmeterでもチェックしてみるも、起こらないので、ますます自分の書き換えた部分が怪しい……。

MeasureCalcは、パーサの実装部分がcharで処理されているので、扱う際にはWCHARからchar(または逆)への変換が挟まってます。どう考えてもこの変換部分としか考えられない。というか弄ったし。

原因の箇所はLiteStep.cppに定義されているConvertToWide()と、ConvertToAscii()でした。
この関数の中では、文字列の変換をWideCharToMultiByte()とMultiByteToWideChar()を使って行っていますが、勘違いから、ソース文字列の長さを指定する部分に「wcslen()で測った文字列の長さ」を渡してしまっていました。これだと、いくら変換コピー先バッファの大きさが十分にあっても、ソース文字列の長さ分の変換コピーがなされるだけで、最後に肝心のヌルターミネータが入らないっぽいです。この場合には、自分で末尾にヌルターミネータをつけてやる必要があったようで……そりゃ終端処理されてないんだからゴミがつくよねと。

ソース文字列にヌルターミネータがついていれば、最後のヌルターミネータまで変換コピーされるように、「実際の文字列の長さ+1」を指定してやるか、そもそも「-1」を指定してやれば、ヌルターミネータを含めた長さとして動いてくれるようです。この「-1」を指定したときの動作を、文字列の長さ分なんだと勘違いしていました。自動計算を何度もやるのをケチりたかったがために入れた長さの指定が、バグを生んでたというわけでした。

結論。むやみに弄るな ヌルターミネータの扱いがどうなるのか、しっかり調べよう。それだけでなく、NULLを渡したときの挙動も、か。

ちなみに勘違いしていた部分の、MSDN日本語版での記述。これだと含まれるのかどうかがわからない。

-1 を指定すると、文字列が NULL で終わっていると見なされ、長さが自動的に計算されます。

MSDNの日本語版は誤訳もありそうだし、英語のほうも見てみた。

If this parameter is set to -1, the function assumes the string to be null-terminated and calculates the length automatically, including the terminating null character. If cchWideChar is set to 0, the function fails.

……最初からこっち読んでればよかった。情報量が違いすぎた。

« [MoE] Color Plate M@STER TRAXX »

- Comments
0 Comments

管理者にだけ表示を許可する
- Trackbacks
0 Trackbacks


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。