Приведение между вариантом и bstr_t, вызывающее несогласованный сбой в Windows 2008 - PullRequest
0 голосов
/ 29 апреля 2010

У нас есть приложение на C #, вызывающее простой класс-оболочку C ++, которое затем вызывает существующую C ++ DLL. Весь код C ++ - это VC ++ 6.0.

Мы получаем противоречивое поведение, но сбой, когда он происходит, всегда происходит в DLL-оболочке C ++ и всегда в одном и том же месте (подтверждено с помощью болезненных операторов ведения журнала). Это никогда не происходит ни в какой среде, кроме Windows 2008, поэтому мы подозреваем, что происходит некая фатальная перегрузка памяти, о которой почему-то Windows 2008 более внимательна.

Вот соответствующий код, если у кого-то есть идеи о том, почему это может привести к сбою, он будет очень признателен. Мы рвали на себе волосы в течение нескольких дней, и сроки проекта сокращаются из-за отсутствия возможности вернуть простую строку обратно в C # ...

Мне сказали, что мы пытались установить VARIANT-результат с помощью VariantInit и очистить его, когда мы закончим с 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;
}

Опять же, любые идеи очень, очень ценятся.

1 Ответ

1 голос
/ 29 апреля 2010

Возможности для кучи и повреждения стека имеются в большом количестве. Не инициализация варианта является самоубийством. Копирование строки C в локальный char [] без проверки длины, всегда будет удачным. Настоящий урон может быть нанесен где угодно, execute_job () или что-то, что запускается полчаса назад.

Рассмотрим инструмент, позволяющий ловить подобные ошибки, например, Coverity.

...