Visual Studio 2017 C++ Tips

この記事は公開されてから時間が経っています

Visual Studio 2017 の C++ で、引っかかった少しの事を忘れそうなので書いておこう!
※ 久し振りに C++ を弄ってみたら、もう浦島太郎になった気分なので、書き殴ってみました ^^..

swscanf に関連した少しの tips
.

swscanf で利用する領域は malloc してはいけない

タブ、空白文字区切りのテキストファイルで、数字、文字、文字 の順で列挙してあるファイルの解析を行おうと思っています
当初、正規表現でマッチさせようか?とも思ったんですが、日本語以外の処理とか、パターンの指定とか正規表現は得意じゃないので…

   if (swscanf_s(wreadbuf, L"%d %512lS %512lS", &year, ptr2,(unsigned)_countof(ptr2), ptr3, (unsigned)_countof(ptr3)) != 3)

こんな感じで ワイド文字で書かれたファイルを読んでみましたけど、この ptr2,ptr3 は、malloc した領域を指定すると領域を破壊するので指定してはいけないようです

ここで ptr2,ptr3 とも、 WCHAR[] ですが、wchar_t *ptr2 = (wchar_t *)malloc(512); などと指定した領域は指定してはいけない様です
実際、%512lS の l を指定しなければ問題は発生しないようですが、コンパイル時に警告が出ます

とくに、処理中は問題なく見えますが、この malloc した領域を free するときにエラーしてしまいます
try catch では拾えません
※ 最近の C++ と Visual Studio に不慣れなのでちょっと追跡し切れていない ^^;.

https://msdn.microsoft.com/ja-jp/library/6ttkkkhh.aspx
ここの 「scanf 関数の型フィールド文字」 の説明に寄れば、ワイド文字列は S を指定する
https://msdn.microsoft.com/ja-jp/library/xdb9w69d.aspx
ここの「scanf 関数の文字幅指定」 の説明に寄れば、ワイド文字列は l のプリフィックスと s または S の型指定子 を指定すると有ります
512 は指定しなくても大丈夫なようですが、それより長い文字は読まないそうです

また、読める文字ですが、こんな感じで開いています
        err = _wfopen_s(&fp, wFileName, L"rt,ccs=UNICODE");
       while(0 != fgetws(wreadbuf, MAX_READ_BUF, fp)) {
       …
       }

メモ帳で作成できる ANSI,Unicode,UTF-8 まではこれでイケます
UTF-16 とか UTF-7 はダメでした(当然 EUC,JIS などもダメです)

※ どこのブログで読んだのか忘れてしまいましたが、 scanf とかで使用する領域は  WCHAR buf[2048] のような配列形式の領域を使用するそうです

ポインターを表示するには %p を使用する

こんな型指定子がある事も知りませんでしたが、
上の ptr2 とかが破壊されているのを確認する為に、
        sprintf_s(buf, MAX_READ_BUF, "%p = %p %s\n%p = %p %s\n%p = %p %s\n",
            (void *)buf1, (void *)ptr2 ,(buf1 == ptr2) ? "match" : "unmatch",
            (void *)buf2, (void *)ptr3, (buf2 == ptr3) ? "match" : "unmatch",
            (void *)buf3, (void *)ptr4, (buf3 == ptr4) ? "match" : "unmatch");

こんな単純な方法を使える様になるまでに、三十分使ってしまいました ^^/

リファレンス読まないとダメだなぁ…

ヒープ領域とスタック領域の拡張

上の文字の読み込みに、結構な大きさのバッファを用意したので、ちょっとスタック領域の拡張とかを行う方法を調べてみました
#pragma comment(linker, "/HEAP:5242880")
#pragma comment(linker, "/STACK:5242880")
これで 5MB 分ですよね..
malloc もヒープ領域から持ってくるそうなので、多少多めに指定しましたが、マルチスレッドなどで分断する事などがあるそうなので、適切なサイズも調べないといけないよね…
テキスト読むだけの領域なら 数KB で十分だと思うけど、文字化けして解析されると一行が膨大な文字数になってしまうと思うので予防線を少し張ってみた!
事実、読めない文字コードで書かれたファイルを読むと、バッファーに一杯の何かが帰ってきます
※ その前に、ファイルのオープン時もバイナリとかに解釈されるらしく、エラーするがこれも上手く拾えない

new と malloc は両方ともヒープ領域から持ってくるそうです
ガベージコレクションの領域もヒープ領域から持ってくるそうです

違いは、スコープの有無、大きさの違い等の様ですが、余り意識しないでも良いんじゃないかと思うけど…
https://msdn.microsoft.com/ja-jp/library/hk1k7x6x.aspx
この 「メモリ割り当て」 とかに少し書いてありますね..

さすが C++ は面倒だぜ!

.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。