gpt4 book ai didi

c++ - 为什么这个程序会崩溃:在 DLL 之间传递 std::string

转载 作者:IT老高 更新时间:2023-10-28 12:59:04 27 4
gpt4 key购买 nike

我无法弄清楚以下崩溃的原因 (MSVC9):

//// the following compiles to A.dll with release runtime linked dynamically
//A.h
class A {
__declspec(dllexport) std::string getString();
};
//A.cpp
#include "A.h"
std::string A::getString() {
return "I am a string.";
}

//// the following compiles to main.exe with debug runtime linked dynamically
#include "A.h"
int main() {
A a;
std::string s = a.getString();
return 0;
} // crash on exit

显然(?)这是由于可执行文件和 DLL 的内存模型不同。会不会是 A::getString() 返回的字符串在 A.dll 中分配并在 main.exe 中释放?

如果是这样,为什么 - 在 DLL(或可执行文件)之间传递字符串的安全方法是什么?不使用带有自定义删除器的 shared_ptr 之类的包装器。

最佳答案

这实际上并不是由不同的堆实现引起的——MSVC std::string 实现不为那么小的字符串使用动态分配的内存(它使用小字符串优化)。 CRT 确实需要匹配,但这次不是你的问题。

发生的情况是您通过违反一个定义规则来调用未定义的行为。

发布和调试版本将设置不同的预处理器标志,您会发现 std::string 在每种情况下都有不同的定义。询问您的编译器 sizeof(std::string) 是什么 - MSVC10 告诉我它在调试版本中为 32,在发布版本中为 28(这不是填充 - 28 和 32 都是 4 个字节` 边界)。

那么发生了什么?变量 s 使用复制构造函数的调试版本来初始化,以复制 std::string 的发布版本。成员变量的偏移量在版本之间是不同的,所以你复制垃圾。 MSVC 实现有效地存储了开始和结束指针——您已将垃圾复制到其中;因为它们不再为 null,所以析构函数会尝试释放它们,但您会遇到访问冲突。

即使堆实现相同,它也会崩溃,因为您正在释放指向从未分配过的内存的垃圾指针。


总而言之:CRT 版本需要匹配,但定义也是如此 - 包括标准库中的定义

关于c++ - 为什么这个程序会崩溃:在 DLL 之间传递 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2322095/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com