*** 异常发生在 C++ Codegear 而不是 Visual C++
Posted
技术标签:
【中文标题】*** 异常发生在 C++ Codegear 而不是 Visual C++【英文标题】:*** exception occurring with C++ Codegear not with Visual C++ 【发布时间】:2019-02-25 11:14:00 【问题描述】:我有这种情况:
用 Visual C++ 编写的数据管理库,但在使用 Embarcadero CodeGear 编写的 C++ 程序中加载和使用 程序 LoadLibrary 和 GetProcAddress 中加载的库和函数问题如下:
该库在 Visual C++ 测试环境中正常 由于***异常使用相同的调用函数序列和相同的参数导致程序崩溃库的简化代码:
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 函数上抛出 *** 异常 程序总是在固定迭代中抛出 *** 异常 (#62643) 我没有看到递归行为,也没有大的堆栈变量(我会说一切都是动态分配的) 我会增加堆栈大小,但在我想检查 Visual C++ 测试环境的堆栈大小与实际运行程序的堆栈大小之前(但我不知道如何获取当前线程堆栈大小)提前致谢,
【问题讨论】:
仔细看看memset(pStruct->Records, 0, sizeof(TmStruct) * pStruct->NumberOfRecords);
你确定要在那里使用sizeof(TmStruct)
吗?
对不起,我写的简化代码出错了,我已经编辑了问题;顺便说一句,仍然有同样的问题;现在谢谢
【参考方案1】:
检查调用约定。确保在任何地方都使用cdecl
或stdcall
。
由于症状看起来 Visual Studio 库是 cdecl
,但 Embarcadero 程序假定它是 stdcall
,因此库和调用者都不会释放堆栈。
【讨论】:
谢谢,我检查了 Embarcadero 编译器的调用约定,它被设置为“C”(即“__cdecl”);对于 VC++ 编译器,我也有“__cdecl”。但是在 VC++ 库头中的函数原型和程序导入头中都明确添加了“__cdecl”关键字,问题完全消失了,让我可以达到迭代 100000+。实际上我不知道为什么没有明确的“__cdecl”关键字,调用约定没有正确设置;对我来说唯一可能的解释是 Embarcadero 程序内部的导入是通过函数指针(不是函数)完成的。 我最近没有使用 Embarcadero 产品的经验,但就我过去使用 Borland Delphi 7 的经验而言,默认调用约定是register
,类似于 Visual Studio @987654326 @, 但不完全兼容.
我的观点是,如果要链接不同的语言模块,依赖默认值并不是一个好主意,而是需要明确指定调用约定。如果不同的编译器使用不同的关键字来调用约定,则可能用宏包装。并且确保您也应该将此显式调用约定应用于函数指针。【参考方案2】:
您正在使用 sizeof(TmStruct)
作为指向 TmRecord
的指针:
memset(pStruct->Records, 0, sizeof(TmStruct) * pStruct->NumberOfRecords);
【讨论】:
对不起,我写的简化代码出错了,我已经编辑了问题;顺便说一句,仍然有同样的问题;现在谢谢以上是关于*** 异常发生在 C++ Codegear 而不是 Visual C++的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 2008 发布版本上的 c++ 应用程序出现未处理异常 - 从函数返回时发生