0

単純な C++ ラッパー クラスを呼び出す C# アプリケーションがあり、それが既存の C++ DLL を呼び出します。C++ コードはすべて VC++ 6.0 です。

一貫性のない動作が得られますが、クラッシュが発生した場合、クラッシュは常に C++ ラッパー DLL 内で発生し、常に同じ場所で発生します (苦痛なログ ステートメントを使用して確認しました)。Windows 2008 以外の環境では発生しないため、何らかの理由で Wi​​ndows 2008 がより注意を払っていることに、致命的ではないものの悪いメモリの破棄が行われていると思われます。

関連するコードは次のとおりです。これがクラッシュする理由について誰かが考えている場合は、大歓迎です。私たちは数日間頭を悩ませてきましたが、プロジェクトのタイムラインは、単純な文字列を C# に戻すことができるようにするために遅れています...

VariantInit を使用して VARIANT vresult を設定し、VariantClear を使用した後にそれをクリアしようとしたと言われましたが、それは役に立ちませんでした。

// JobMgrDll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "JobMgrDll.h"
#include "jobmgr.h"

CString gcontext;
CString guser;
CString ghost;
CString glog;
JOBMGRDLL_API int nJobMgrDll=0;

extern "C" JOBMGRDLL_API  char*  perform_billcalc(char* cmd, char* context, char* user,char* host,BSTR* log,int* loglen)
{
 char* result = new char[1000];
 memset(result,0,999);
 result[999] = '\0';
 bstr_t bt_command = cmd;

 UUID uuid = __uuidof(BRLib::Rules);
 VARIANT vresult;
 char *p_rv;
 gcontext = context;
 guser = user;
 ghost = host;
 write_log("execute_job");
 p_rv = execute_job(uuid, "none", bt_command, &vresult);
 write_log("DONE execute_job");
 CString message;

 write_log ("Intializing bstr_t with variant");  // WE ALWAYS GET HERE
 bstr_t res(vresult); 

 //message.Format("%s result = %s",p_rv,res);
 //write_log(message);
 write_log("copying Result");  // WE DON'T ALWAYS GET HERE, BUT SOMETIMES WE DO
 strcpy(result,(char*)res);
 write_log(CString(result));

 *loglen = glog.GetLength();
 *log = glog.AllocSysString();

 return result;
}

繰り返しになりますが、どんなアイデアでも大歓迎です。

4

1 に答える 1

1

ヒープとスタックが破損する可能性はたくさんあります。バリアントを初期化しないことは自殺行為です。長さをチェックせずに C 文字列をローカルの char[] にコピーすることは、常に幸運であることを望んでいます。実際の損害は、execute_job() や 30 分前に実行されたものなど、どこでも発生する可能性があります。

このような間違いを検出するためのツール、Coverity のようなものを検討してください。

于 2010-04-29T17:31:00.693 に答える