DLL内の関数に渡し、その関数内でnew演算子で領域確保したポインタを開放するには?

解決


どら  2007-10-16 21:20:57  No: 66591

度々の質問で済みません。

Windows XP SP2 + VS.NET 2003 Ent(SDK)で開発しています。

私がポインタをきちんと理解していないからかもしれませんが・・・

例えば、Win32アプリ作成のソースの中で以下の関数を用意するものとします。

void test(char **test, UINT *ErrorCode)
{
  if(*test != NULL)
  {
    delete[] *test;
    *test = NULL;
  }

  *test = new char[lstrlen("テスト") + 1];
  if(*test == NULL)
  {
    *ErrorCode = 1;
    return;
  }
  lstrcpy(*test, "テスト");

  *ErrorCode = 0;
  return;

}

これをWinMain関数等で呼び出した場合、

char *Result = NULL;
UINT ErrorCode;

test(&Result, &ErrorCode);
MessageBox(NULL, Result, "結果", MB_OK);
if(Result != NULL)
{
  delete[] Result;
  Result = NULL;
}

というように、Resultに関しては、deleteでバッファを開放する必要がありますよね。

これと同じ動きをする(引数も同じ)関数をDLLから

HMODULE hMod;
char *Result = NULL;
UINT ErrorCode;
void (*f)(char**, UINT*);

hMod = LoadLibrary("GetPCModel.dll");
if(hMod == NULL)
{
  MessageBox(NULL, "DLLロードエラー", "終了", MB_OK);
  return -1;
}

f = (void (*)(char**, UINT*))GetProcAddress(hMod, "test");
(*f)(&Result, &ErrorCode);

MessageBox(NULL, Result, "結果", MB_OK);

if(Result != NULL)
{
  delete[] Result;             //<--ここで例外が発生
  Result = NULL;
}
FreeLibrary(hMod);

以上のように呼び出した場合、delete[] の部分
で例外が発生してしまいます。

DLLで呼び出した場合は、バッファの開放の仕方が異なるのでしょうか?
それとも、DLLでこの様な事をしてはいけないのでしょうか?

DLL作成の経験が殆どないため、不勉強で大変申し訳ありませんが、どなたかご教授
いただけると幸いです。

よろしくおねがいいたします。


tetrapod  2007-10-16 22:05:47  No: 66592

DLL の開発言語と EXE の開発言語が違う (DLL は VC++ で EXE は BCC など)
DLL のコンパイルオプションと EXE のコンパイルオプションが違う
ような場合 new/delete の処理内容が不一致で動作しないことがありうる
なので new/delete は組にして EXE 内、または DLL 内に組み込むべし。

--hoge.dll--
char* AllocaterFunc() { new char[100] などの結果を返す }
void DeallocatorFunc(char* p) { delete[] p; }
のように作っておくのが普通。


どら  2007-10-17 00:02:32  No: 66593

terapod さん、ありがとうございました。

DLL内にもう一つ関数

DllExport void FreeCharBuf(char **Buf)
{
  if(*Buf != NULL)
  {
    delete[] *Buf;
    *Buf = NULL;
  }
  return;
}

みたいな関数を追加し、exe側のソースので取得した文字列Resultを使った後

void (*f2)(char**);
f2 = (void (*)(char**))GetProcAddress(hMod, "FreeModelCharBuf");
(*f2)(&Result);
FreeLibrary(hMod);

としたところ、問題無く解決しました!!
ありがとうございました、本当に助かりました!!


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加