在不同的编译器版本中调用new[]和delete[]

Calling new [] and delete [] in different compiler versions

本文关键字:new delete 调用 编译器 版本      更新时间:2023-10-16

为了实现一个只在旧编译器版本下运行的框架,我不得不为我的动态链接库设计一个接口,该接口可以在不同的编译器版本中工作。我想出了一个返回字符串的代码:

char * returnCharStr() {
...
auto ret = new char[ str.length ];
... // copy string data into ret
return ret;
}

现在,为了避免内存泄漏,我必须在某个时刻(在另一个编译器版本编译的代码中)对返回的字符串调用delete []

...
auto cstr = returnString();
... // work with cstr
delete [] cstr;

此代码在运行时崩溃。解决方案是在编译到动态库(returnCharStr()函数所在的库)中的函数内部调用delete []。问题是,为什么代码在delete []语句上崩溃?

用一个框架分配的内存必须由同一个框架释放,尤其是当内存在不同的环境、不同的编译器等之间传递时。您无法控制调用方对内存的处理,调用方也不知道内存是如何分配的,因此无法直接释放内存。

要做你正在尝试的事情,你必须暴露另一个函数来正确释放内存,例如:

char * returnCharStr() {
...
char* ret = new char[ str.length ];
// copy string data into ret...
return ret;
}
void freeCharStr(char *str) {
delete[] str;
}

char* cstr = returnString();
// work with cstr...
freeCharStr(cstr);

我在不同版本的编译器之间没有遇到过这样的问题,因为内存的分配方式并没有随着时间的推移而发生太大变化。

然而,有些编译标志彼此之间肯定不兼容,例如/MT/MTd。它们使用不同类型的分配器和解除分配器(调试版本添加填充缓冲区来检查是否存在"简单"缓冲区溢出,并在检测到这种情况时生成错误)

如果你不知道现有的二进制文件是如何编译的,那么很难猜测,尽管我认为有一种方法可以查看二进制文件,但我真的不知道该查看什么。不过,这可能是另一个stackoverflow问题的主题。

如果您可以控制两个二进制文件的编译,那么只需确保使用相同的标志即可。如果你不在新的二进制文件中全部尝试,看看哪一个有效。。。我想它将是一个没有d(调试)的,所以你可能必须在多线程打开或不打开的情况下进行测试