从RAD Studio 10.3项目调用BCB6编译DLL的C++函数出现访问违规问题
问题根因
核心原因是不同版本编译器的ABI(应用程序二进制接口)不兼容,具体体现在两点:
- 标准库、VCL类的内存布局差异
BCB6发布于2002年,其内置的std::vector、std::string基于老旧的SGI STL实现,AnsiString的内部字段布局也和RAD Studio 10.3的实现完全不同。即使你设置了相同的结构体对齐规则,两个编译器对同一种类型的内存排布、成员偏移量的定义也存在差异。你在10.3环境中构造的std::vector对象,传入BCB6编译的DLL后,DLL会按照BCB6的STL规则解析这段内存,自然会读出80000+的错误长度,遍历的时候就会访问到非法地址。 - 运行时堆不统一
BCB6和RAD Studio 10.3的C++运行时库是完全独立的,各自管理自己的进程堆。你在10.3环境中分配的对象内存(包括new出来的结构体、STL容器自动申请的内存),在BCB6的运行时中没有对应的堆管理记录,就算布局一致,跨模块的内存操作也极易触发异常。
关于struct改为class的效果
完全不能解决问题。C++中struct和class的唯一区别只有默认成员访问权限、默认继承类型是public还是private,二者的内存排布规则完全一致,修改后不会改变任何二进制层面的表现。
可行的解决方案
- 将DLL接口改为纯C兼容接口,不要传递STL容器、VCL类等跨版本不兼容的复杂类型:比如字符串统一用
const char*传递,vector替换为「数组长度+元素首指针」的参数组合,接口内部再转换为对应环境的类型使用。 - 用RAD Studio 10.3重新编译该DLL,保证调用方和DLL的编译器版本、运行时库编译选项完全一致。
- 用COM规范封装DLL接口,使用自动化兼容的标准类型传递参数。
内容的提问来源于stack exchange,提问作者kvirk
相关产品推荐
相关产品推荐

