使用 C++ Codegear 而不是使用 Visual C++ 发生 Stackoverflow 异常
Stackoverflow exception occurring with C++ Codegear not with Visual C++
我有这个场景:
- 用 Visual C++ 编写但在使用 Embarcadero CodeGear 编写的 C++ 程序中加载和使用的数据管理库
- 在程序 LoadLibrary 和 GetProcAddress 中加载的库和函数
问题如下:
- 库在Visual C++测试环境下正常
- 由于 Whosebug 异常使用相同参数的相同调用函数序列导致程序崩溃
库的简化代码:
struct TmRecordValue
{
UINT8 RecordValue[128];
};
struct TmRecord{
TmRecordValue RecordValues[2];
};
struct TmStruct
{
UINT32 NumberOfRecords;
TmRecord* Records;
};
void InitializeStruct(TmStruct* pStruct, int pNumberOfRecords)
{
memset(pStruct, 0, sizeof(TmStruct));
pStruct->NumberOfRecords = pNumberOfRecords;
pStruct->Records = new TmRecord[pStruct->NumberOfRecords];
memset(pStruct->Records, 0, sizeof(TmRecord) * pStruct->NumberOfRecords);
}
void AddRecordToStruct(TmStruct* pStruct, int pRecordIndex, char* pFirstValue, char* pSecondValue)
{
strcpy_s(reinterpret_cast<char*>(pStruct->Records[pRecordIndex].RecordValues[0].RecordValue), 128, pFirstValue);
strcpy_s(reinterpret_cast<char*>(pStruct->Records[pRecordIndex].RecordValues[1].RecordValue), 128, pSecondValue);
}
程序的简化代码:
TmStruct *struct1 = new TmStruct();
int RecordsQuantity = 100000;
InitializeStruct(struct1, RecordsQuantity);
for (int i = 0; i < RecordsQuantity; i++)
{
AddRecordToStruct(struct1, i, "first", "second");
}
评论:
- 程序 运行 RecordsQuantity = {10, 100, 1000, 10000} 正常,但在 100000 时崩溃
- 程序在 AddRecordToStruct 函数上抛出 Whosebug 异常
- 程序总是在固定迭代中抛出 Whosebug 异常
(#62643)
- 我没有看到递归行为,也没有大堆栈变量(我会说所有动态分配的)
- 我会增加堆栈大小,但在我想检查 Visual C++ 测试环境的堆栈大小与实际 运行 程序的堆栈大小之前(但我不知道如何获取当前线程堆栈大小)
提前致谢,
您正在使用 sizeof(TmStruct)
作为指向 TmRecord
的指针:
memset(pStruct->Records, 0, sizeof(TmStruct) * pStruct->NumberOfRecords);
检查调用约定。确保在任何地方都使用 cdecl
或 stdcall
。
因为根据症状看起来 Visual Studio 库是 cdecl
但 Embarcadero 程序假定它是 stdcall
,因此库和调用者都不会释放堆栈。
我有这个场景:
- 用 Visual C++ 编写但在使用 Embarcadero CodeGear 编写的 C++ 程序中加载和使用的数据管理库
- 在程序 LoadLibrary 和 GetProcAddress 中加载的库和函数
问题如下:
- 库在Visual C++测试环境下正常
- 由于 Whosebug 异常使用相同参数的相同调用函数序列导致程序崩溃
库的简化代码:
struct TmRecordValue
{
UINT8 RecordValue[128];
};
struct TmRecord{
TmRecordValue RecordValues[2];
};
struct TmStruct
{
UINT32 NumberOfRecords;
TmRecord* Records;
};
void InitializeStruct(TmStruct* pStruct, int pNumberOfRecords)
{
memset(pStruct, 0, sizeof(TmStruct));
pStruct->NumberOfRecords = pNumberOfRecords;
pStruct->Records = new TmRecord[pStruct->NumberOfRecords];
memset(pStruct->Records, 0, sizeof(TmRecord) * pStruct->NumberOfRecords);
}
void AddRecordToStruct(TmStruct* pStruct, int pRecordIndex, char* pFirstValue, char* pSecondValue)
{
strcpy_s(reinterpret_cast<char*>(pStruct->Records[pRecordIndex].RecordValues[0].RecordValue), 128, pFirstValue);
strcpy_s(reinterpret_cast<char*>(pStruct->Records[pRecordIndex].RecordValues[1].RecordValue), 128, pSecondValue);
}
程序的简化代码:
TmStruct *struct1 = new TmStruct();
int RecordsQuantity = 100000;
InitializeStruct(struct1, RecordsQuantity);
for (int i = 0; i < RecordsQuantity; i++)
{
AddRecordToStruct(struct1, i, "first", "second");
}
评论:
- 程序 运行 RecordsQuantity = {10, 100, 1000, 10000} 正常,但在 100000 时崩溃
- 程序在 AddRecordToStruct 函数上抛出 Whosebug 异常
- 程序总是在固定迭代中抛出 Whosebug 异常 (#62643)
- 我没有看到递归行为,也没有大堆栈变量(我会说所有动态分配的)
- 我会增加堆栈大小,但在我想检查 Visual C++ 测试环境的堆栈大小与实际 运行 程序的堆栈大小之前(但我不知道如何获取当前线程堆栈大小)
提前致谢,
您正在使用 sizeof(TmStruct)
作为指向 TmRecord
的指针:
memset(pStruct->Records, 0, sizeof(TmStruct) * pStruct->NumberOfRecords);
检查调用约定。确保在任何地方都使用 cdecl
或 stdcall
。
因为根据症状看起来 Visual Studio 库是 cdecl
但 Embarcadero 程序假定它是 stdcall
,因此库和调用者都不会释放堆栈。