Why does this program crash: passing of std::string between DLLs(为什么这个程序会崩溃:在 DLL 之间传递 std::string)
问题描述
我无法弄清楚以下崩溃的原因 (MSVC9):
I have some trouble figuring out why the following crashes (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 中释放?
Obviously (?) this is due to the different memory models for the executable and DLL. Could it be that the string A::getString()
returns is being allocated in A.dll and freed in main.exe?
如果是这样,为什么 - 以及在 DLL(或可执行文件,就此而言)之间传递字符串的安全方法是什么?不使用带有自定义删除器的 shared_ptr 之类的包装器.
If so, why - and what would be a safe way to pass strings between DLLs (or executables, for that matter)? Without using wrappers like shared_ptr with a custom deleter.
推荐答案
这实际上并不是由不同的堆实现引起的 - MSVC std::string 实现不会为这么小的字符串使用动态分配的内存(它使用小字符串优化).CRT 确实需要匹配,但这不是你这次的问题.
发生的情况是您违反了一个定义规则,从而调用了未定义的行为.
What's happening is that you're invoking undefined behaviour by violating the One Definition Rule.
发布和调试版本将设置不同的预处理器标志,您会发现 std::string
在每种情况下都有不同的定义.询问您的编译器 sizeof(std::string)
是什么 - MSVC10 告诉我它在调试版本中为 32,在发布版本中为 28(这不是填充 - 28 和 32 都是 4 个字节`边界).
The release and debug builds will have different preprocessor flags set, and you'll find that std::string
has a different definition in each case. Ask your compiler what sizeof(std::string)
is - MSVC10 tells me that it's 32 in a debug build and 28 in a release build (this isn't padding - 28 and 32 are both 4 bytes` boundaries).
发生什么事了?变量 s
使用复制构造函数的调试版本进行初始化,以复制 std::string
的发布版本.不同版本的成员变量的偏移量不同,所以你复制垃圾.MSVC 实现有效地存储了开始和结束指针 - 您已将垃圾复制到它们中;因为它们不再是 null,析构函数试图释放它们,你会得到访问冲突.
So what's happening? Variable s
is initialized using the debug version of the copy constructor to copy a release version of std::string
. The offsets of the member variables are different between the versions, so you copy garbage. The MSVC implementation effectively stores begin and end pointers - you've copied garbage into them; because they're no longer null, the destructor tries to free them and you get an access violation.
即使堆实现相同,它也会崩溃,因为您正在释放指向从未分配过的内存的垃圾指针.
Even if the heap implementations were the same it would crash, as you're freeing garbage pointers to memory that was never allocated in the first place.
总而言之:CRT 版本需要匹配,但定义也需要匹配 - 包括标准库中的定义.
In summary: the CRT versions need to match but so do the definitions - including the definitions in the standard library.
这篇关于为什么这个程序会崩溃:在 DLL 之间传递 std::string的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么这个程序会崩溃:在 DLL 之间传递 std::string
基础教程推荐
- 使用从字符串中提取的参数调用函数 2022-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 从 std::cin 读取密码 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 为什么语句不能出现在命名空间范围内? 2021-01-01