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

时间:2017-01-08 19:55:31

标签: c++ visual-studio

促进仅在旧编译器版本下运行的框架,我被迫为我的动态链接库设计一个接口,该接口适用于不同的编译器版本。我想出了返回字符串的代码:

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

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

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

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

2 个答案:

答案 0 :(得分:1)

用一个框架分配的内存必须由同一个框架释放,特别是当该内存在不同的环境,不同的编译器等之间传递时。您无法控制调用者对内存和调用者的操作没有概念如何分配内存因此无法直接释放它。

要执行您正在尝试的操作,您必须公开另一个函数以正确释放内存,例如:

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);

答案 1 :(得分:-3)

我在编译器版本之间没有这样的问题,因为内存分配的方式随着时间的推移没有太大变化。

但是,/MT/MTd之间的compilation flags绝对不相容。这些使用不同类型的分配器和解除分配器(调试版本添加填充缓冲区来检查是否有"简单"缓冲区溢出并在检测到这些时产生错误。)

如果您不知道现有的二进制文件是如何编译的,那么它很难猜到,虽然我认为有一种方法可以查看二进制文件,但我真的不知道该怎么做看着。不过,这可能是另一个stackoverflow问题的主题。

如果您可以控制两个二进制文件的编译,那么请确保使用相同的标志。如果你没有在你的新二进制文件中尝试所有这些,看看哪一个有效......我想它将是没有d(调试)的那个,所以你可能需要测试是否有多线程打开了。