我似乎在删除char*
数组时遇到问题。当delete[]
被调用时,它会因堆损坏而崩溃:
typedef struct _CDB_SYMBOL_INFO {
char * name;
unsigned long address;
unsigned long value;
} CDB_SYMBOL_INFO;
// ...
for each( Symbol ^ symbol in bls->Symbols )
{
CDB_SYMBOL_INFO symbol_info;
symbol_info.name = new char[symbol->Name->Length];
Marshal::Copy( symbol->Name->ToCharArray(), 0, IntPtr( (char*) symbol_info.name ), symbol->Name->Length );
// see enumerate_cdb_symbols_callback(..)
cdb_call_back(&symbol_info, *call_back);
delete[] symbol_info.name; // Crashes here
}
// ...
我在这里看不到问题..
static int enumerate_cdb_symbols_callback(CDB_SYMBOL_INFO * info, void * call_back)
{
EnumerateSymbolsCallBack *cb = (EnumerateSymbolsCallBack*)call_back;
Symbol * symbol = alloc_symbol();
cb(0, symbol);
return 0;
}
答案 0 :(得分:3)
您为一个16位元素数组调用Marshal::Copy
重载(.NET System::Char
不是C ++ char
!),第四个参数是数字元素不是字节数,因此您实际上复制symbol->Name->Length * 2
个字节,这是缓冲区大小的两倍。产生的溢出会破坏堆元数据,导致delete[]
崩溃。
使用wchar_t
类型的缓冲区,它是匹配System::Char
的C ++类型,或者将字符串转换为ASCII,可以将ToCharArray()
替换为Encoding::ASCII::GetBytes(symbol->Name)
。或UTF-8,在这种情况下,您不能假设symbol->Name->Length
是必要的缓冲区大小。
更简单的方法是使用C ++ / CLI附带的marshal_as
库:
#include <msclr\marshal_cppstd.h>
using namespace msclr::interop;
for each( Symbol ^ symbol in bls->Symbols )
{
std::string sym_name = marshal_as<std::string>(symbol->Name);
CDB_SYMBOL_INFO symbol_info;
symbol_info.name = &sym_name[0];
// see enumerate_cdb_symbols_callback(..)
cdb_call_back(&symbol_info, *call_back);
}
它执行一些未指定的单字节字符编码(很可能是ASCII),并使用RAII自动释放内存。