バグ:CStringのGetBufferを用いて既存の処理と連携する

Posted: 2012年12月24日

CStringのGetBufferでよく書いてしまうバグを紹介します。
Javaなどの言語からC++を使用するようになった時にやりそうなことです。

プログラムプログラム:

 #include <stdio.h>
 #include <Windows.h>

 int main(int argc, char *argv[])
 {
    DWORD dwNameLength;
    CString strName;


    // ユーザ名の取得
    if (GetUserName(strName.GetBuffer(), &amp;dwNameLength) == FALSE) {
        return -1;
    }

    // 処理

    return 0;
 }

このプログラムにどのような指定文字列を抜き出し処理のバグがあると思いますか?

  • GetBufferの引数なしを選択している
  • GetBufferに対応するReleaseBufferを行なっていない

改善版プログラム改善版プログラム:

 #include <stdio.h>
 #include <Lmcons.h>
 #include <Windows.h>

 int main(int argc, char *argv[])
 {
    DWORD dwNameLength;
    CString strName;


    // ユーザ名の取得
    if (GetUserName(strName.GetBuffer(UNLEN + 1), &amp;dwNameLength) == FALSE) {
        return -1;
    }

    // 処理

    strName.ReleaseBuffer();
    return 0;
 }

解説解説:

GetBufferを行った場合は、ReleaseBufferを行う必要があります。
その理由は、GetBufferで領域を確保するため、領域を解放するためにReleaseBufferを実行します。

GetBuffer引数なしは、
現在確保している領域を取得します。
そして、領域は増減しないためメモリーの破壊を行い場合があります。

そのため、GetBuffer(UNLEN + 1)のように必要な領域サイズを渡すことで
領域を確保しするためメモリーの破壊は行われません。

GetBuffer(UNLEN + 1)はnew TCHAR[UNLEN + 1]と同等です。
個人的には、解放する必要があることが分かるnew TCHAR[UNLEN + 1]を使用してしまいます。

しかし、new TCHAR[UNLEN + 1]をCStringにする場合は、GetBufferのほうが
無駄に領域を確保する必要がないため(TCHARとCSTringの2つで確保せずに済む)
そのような場合は、使うべきです。

カテゴリー: バグ, プログラム | タグ: , , , | コメント無し »

コメント