ファイル名の文字列を作る処理でGetBufferを使ってバッファを取得する意味が分からない

投稿者: Anonymous

以下のサイトを参考に、MFCでアプリケーションを終了したときのアプリケーションの座標を取得し、再度アプリケーションを起動したときに前回アプリケーションを終了したときの座標にアプリケーションを起動させる処理を作っていますが、以下の参考サイトにある、

LPTSTR pBuff = csInifile.GetBuffer(MAX_LEN + 1);

という処理が何のためにしているかをちゃんと理解したくて質問させて頂きました。

参考にしているサイト:
http://pg-sample.sagami-ss.net/?eid=29

これを理解するために私なりにしたことは、
まずバッファが何かよく分からなかったので、調べました。
結果、コンピュータとハードディスクなど、処理速度に大きな差があるときに、コンピュータが一時的にデータを溜めこんで、ハードディスクに読み書きをしている間に待ち時間が発生しないようにするための仕組みだと理解しました。

しかし、なぜ上記のGetBufferの処理でパスの文字列を作るためにバッファを作る必要があるか分かりませんでした。分からない理由は、パスの文字列を作るだけならコンピュータとハードディスクに処理速度は関係なくすぐに作れるのでは?と思ったからです。

ただ、仮説としては、コンピュータとハードディスクに処理速度の差は圧倒的で、パスをGetModuleFileNameで作るだけでもバッファがないと本当にコンマ数秒くらい遅延するのかと思いました。(しかしながら、ただ単にGetModuleFileNameの第二引数の型がLPTSTRなので、CString型であるcsInifileLPTSTRにキャストすることがメインの目的でGetBufferを使用されているのかもしれませんが…)

上記、教えて頂けるとありがたいです。どうかよろしくお願いします。

解決

いくつか誤解と言うか「理解不足」があります。

バッファについて

コンピュータのソフトウェア用語として使われるバッファは、少し長めに言うと「(○○のための)バッファ(用のデータ(メモリ)領域)」になるでしょう。
カッコ内の部分は記述されることもあるし省略されることもあります。まあ省略されることが多いでしょうが。

ハードディスクに係わる仕組みは大きな1例であって全てではありません。
@sayuri さん回答のように、「何の」ためのバッファか、については使われ方によってそれぞれ違い、目的は山のように存在します。

質問記事の場合は以下に説明しますが、処理を速くするのが目的ではありません。

ファイル名の文字列を作る処理?

質問タイトルの「ファイル名の文字列を作る処理」そのものは間違ってはいないのですが、その4行の処理も2行づつ別々の処理に分けることができます。

質問にも引用された行を含む最初の2行は、現在のプロセス(自分自身のプログラム)の実行可能ファイルのパスを文字列変数に取得します。
2行目のGetModuleFileNameW functionの第2、第3パラメータには、パスを格納するバッファへのポインタとそのバッファのサイズを指定する必要がありますし、そのバッファはGetModuleFileNameを呼び出す前に確保されている必要があります。

しかし、CString csInifile変数はクラスメンバとして定義されているだけであり、この時点ではこの変数に空文字列を示す終端の0くらいしかデータは存在しておらず、パスを格納するのに十分なバッファは確保されていません。

そのため、「実行可能ファイルのパスを格納するバッファ」をMAX_LEN + 1文字の長さを指定して確保するために行っている 、というのが質問の処理です。

確保した後、実行可能ファイルのパスを取得するためにGetModuleFileNameを呼び出しています。

そしてその次の2行が狭義の「ファイル名の文字列を作る処理」であり、実行可能ファイルのパスの最後のexeiniに書き換えて、iniファイル名のパスを作っています。

最終的にiniファイル名のパスを格納しておくCString変数があるので、作業用として実行可能ファイルのパスを格納するバッファの確保も、その変数のGetBufferメソッドで行っているのでしょう。

行数も変わらないしあまり意味はありませんが、MAX_LENのサイズが小さいならGetBufferを使わずに自動変数としてバッファを定義して使う以下のような方法も考えられます。
参照記事に定義された2048くらいでも問題無く動作するでしょう。

TCHAR pBuff[MAX_LEN + 1];
DWORD PathLen = GetModuleFileName(NULL, pBuff, MAX_LEN) - 3;
errno_t ernt = _tcscpy_s(&pBuff[PathLen], (MAX_PATH - PathLen), _T("ini"));
csInifile = pBuff;
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *