带指针的C ++ Struct:构造函数和析构函数

时间:2012-10-12 09:28:24

标签: c++ dll struct destructor

我遇到一个调用DLL来执行优化任务的模拟程序的问题。在研究了这个问题一段时间之后,我认为我的问题在于我在DLL返回所需信息后用来释放内存的析构函数。仿真程序是在Borland C ++ Builder v6上开发的,DLL是在MS Visual C ++ 2005上开发的。

对于模拟程序(P)和用于交换数据的DLL,我创建了两个结构InputCPLEXOutputCPLEX以及一个带有两个参数的函数optimize:一个类型为{的对象{1}}和InputCPLEX类型的一个对象。两个结构都在头文件OutputCPLEX中声明,该文件属于P项目和DLL项目。

structures.hInputCPLEX结构都有OutputCPLEXint成员,所以基本上文件int*如下:

structures.h

我的想法是,在模拟过程中(P的执行),我定期调用DLL来解决优化问题,因此//structures.h struct InputCPLEX{ public: int i; int* inputData; } struct OutputCPLEX{ public: int j; int* outputData; } 是与我的优化问题中的变量对应的数组{{1是我的变量的最佳值数组。我知道使用STL容器会更容易,例如inputData,但是如果我错了,请纠正我 - 似乎很难在两个不同的编译器之间交换STL对象。

以下是我的主文件中的内容(在P中):

outputData

一年多以来,我一直在文件vector<int>中使用此代码而没有任何构造函数或析构函数,因此未执行结构成员的初始化。你可能已经猜到了,我不是C ++的专家,事实上它恰恰相反。我还想强调一点,我没有编写大部分模拟程序,只是一些函数,这个程序是由几个开发人员开发了10多年,结果非常混乱。

然而,直到最近,一切都运转良好。我决定向DLL提供更多信息(用于优化目的),因此在运行大型模拟(涉及大型数据集)时,模拟程序已经系统地崩溃。额外的信息是两个结构中的指针,我的猜测是程序泄漏了内存,所以我尝试编写构造函数和析构函数,以便分配给结构//main.h InputCPLEX* input; OutputCPLEX* output; int* var; int* sol; //main.cpp [...] //lots of code input = new InputCPLEX; output = new OutputCPLEX; int n = X; //where X is an integer var = new int[n]; [...] //some code to fill var input->i = n; input->inputData = var; optimize(input,output); //calls the DLL int m = output->j; sol = new int[n]; sol = output->outputData; [...] //some code to use the optimized data delete[] var; delete[] sol; delete input; delete output; [...] //lots of code structures.h的内存可以是妥善管理。我尝试了下面的代码,我发现在网上搜索:

input

但它似乎不起作用:程序在很短的时间后崩溃得更快。有人可以帮我识别代码中的问题吗?我知道可能有其他因素影响我的程序的执行,但如果我删除output文件中的构造函数和析构函数,那么模拟程序仍然能够执行小型模拟,涉及小数据集。

非常感谢你的帮助, 大卫。

3 个答案:

答案 0 :(得分:1)

你必须使用一致的新方法 - 删除。如果new[]获得了某些内容,则应delete[]删除该内容,如果new - >按delete删除。在您的代码中,您可以input创建outputnew,但可以通过delete[]删除。

顺便说一句,你不必在删除前检查指针为零。 delete处理零指针没有问题。

答案 1 :(得分:1)

我在您的代码中看到了几个问题:

1)内存泄漏/双重删除:

sol = new int[n];
sol = output->outputData; 

这里你在初始化之后立即覆盖sol指针,并且new int[n]分配的数据被泄露。你也可以在sol中双重删除指针 - 在output的析构函数中第二次删除指针。与var相同的问题 - 您通过显式delete[]input的析构函数将其删除两次。

在使用delete添加析构函数后,会出现双删除问题,看起来就像它没有问题一样。

同样@Riga提到你使用new[]来分配数组,但在析构函数中使用delete而不是delete[]。这是不正确的,这是未定义的行为。尽管这看起来不像崩溃的原因。在现实世界中,大多数编译器对于内置和POD类型实现deletedelete[]没有区别。只有当delete具有非平凡析构函数的对象数组时,才会出现严重问题。

2)分配output->outputData的位置?如果在DLL中它是另一个问题,因为如果它是在用另一个编译器实现的DLL中分配的话,通常无法安全地释放主程序中的内存。原因是不同的new/delete实现和主程序和DLL的运行时使用的不同堆。

你总是要在同一侧分配/释放内存。或者使用一些常见的低级API - 例如<{1}}或VirtualAlloc()/VirtualFree()具有相同的堆句柄。

答案 2 :(得分:0)

这看起来很奇怪:

int m = output->j; 
sol = new int[n];
sol = output->outputData;

据我所知,你以m为单位返回大小但是用n分配 然后通过将指针(sol)设置为outputData来覆盖数组 我认为你的意思是:

int m = output->j; 
sol = new int[m];
memcpy(sol,output->outputData,sizeof(int)*m);