*** 异常发生在 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-&gt;Records, 0, sizeof(TmStruct) * pStruct-&gt;NumberOfRecords);确定要在那里使用sizeof(TmStruct)吗? 对不起,我写的简化代码出错了,我已经编辑了问题;顺便说一句,仍然有同样的问题;现在谢谢 【参考方案1】:

检查调用约定。确保在任何地方都使用cdeclstdcall

由于症状看起来 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++的主要内容,如果未能解决你的问题,请参考以下文章

python中的异常处理:厌而不舍

C++入门C++的异常管理机制介绍

Visual Studio 2008 发布版本上的 c++ 应用程序出现未处理异常 - 从函数返回时发生

[c++]第八章概念题 | 异常

C++程序运行过程中发生异常闪退,很有可能是这三个原因导致的

C++ 捕获程序异常奔溃minidump