msi*_*msi 25 c++ dll memory-management visual-c++
我无法弄清楚以下崩溃的原因(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
Run Code Online (Sandbox Code Playgroud)
显然(?)这是由于可执行文件和DLL的不同内存模型.可能是字符串A::getString()返回是在A.dll中分配并在main.exe中释放?
如果是这样,为什么 - 以及在DLL(或可执行文件)之间传递字符串的安全方法是什么?不使用shared_ptr这样的包装器和自定义删除器.
Joe*_*oeG 52
这实际上并不是由不同的堆实现引起的 - MSVC std :: string实现不为小的字符串使用动态分配的内存(它使用小字符串优化).CRT确实需要匹配,但这次不是你的意思.
发生的事情是你通过违反一个定义规则来调用未定义的行为.
发布和调试版本将设置不同的预处理程序标志,并且您会发现std::string在每种情况下都有不同的定义.问你的编译器是什么sizeof(std::string)- MSVC10告诉我它在调试版本中是32,在发布版本中是28(这不是填充 - 28和32都是4字节`边界).
那么发生了什么?s使用复制构造函数的调试版本初始化变量以复制发行版本std::string.成员变量的偏移量在版本之间是不同的,因此您可以复制垃圾.MSVC实现有效地存储了开始和结束指针 - 你已经将垃圾复制到它们中; 因为它们不再为null,析构函数会尝试释放它们,并且您会获得访问冲突.
即使堆实现是相同的,它也会崩溃,因为你将垃圾指针释放到从未首先分配的内存中.
总结:CRT版本需要匹配,但定义也是如此 - 包括标准库中的定义.
| 归档时间: |
|
| 查看次数: |
16330 次 |
| 最近记录: |