在何处/如何删除另一个对象中的对象,在创建它的函数之外 [英] Where/how to delete an object within another object, outside the function that it was created in

查看:209
本文介绍了在何处/如何删除另一个对象中的对象,在创建它的函数之外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了解决这个问题坏内存管理?类成员(布尔)值大于1,在递归函数,我运行整个程序在Valgrind和发现一些内存泄漏问题之前发生的步骤。在函数CMFLoader中有2个确定丢失的问题。



(这里MyDataset是Molecule对象的向量,每个Molecule对象包含一个Elements对象) p>

在CMFLoader :: loadFile(vector& MyDataset)中,我原来有

  MyDataset.push_back(readMolecule(in_file,word); 

其中CMFLoader :: readMolecule返回一个Molecule对象在readMolecule函数中,创建了一个新的Molecule对象(但是直到main的结尾才被删除,稍后会更多)。

  Molecule * CMFLoader :: readMolecule(ifstream& in_file,string id)
{
Molecule * my_mol = new Molecule(id);
// readFormula函数
my_mol-> setFormula(readFormula(ss));
return my_mol;
}

其中CMFLoader :: readFormula返回一个Element对象,还有一个Molecule :: setFormula函数将其保存到Molecule对象中。在readFormula中

  Elements * CMFLoader :: readFormula(stringstream& ss)
{
Elements * my_formula = new Elements();
...
return my_formula;
}



我遇到了问题在这里,稍后在主程序中。具体问题发生在HammettCheck :: checkHammett步骤。然后我改变了上面的CMFLoader函数这样的东西。我遇到的问题似乎已经消失了(但在程序后面还有其他问题,毫无疑问与内存泄漏有关):



在CMFLoader :: loadFile

  Molecule * new_mol = new Molecule(word); 
MyDataset.push_back(readMolecule(in_file,word,new_mol));

其中readMolecule现在接受一个新的参数Molecule *,并在函数中删除new运算符。类似地,在readFormula中,我现在有

  Elements * new_formula = new Elements(); 
my_mol-> setFormula(readFormula(ss,new_formula));

等。



内存泄漏问题不能删除!但是,我不能在任何CMFLoader函数中放入删除操作符,因为对象稍后在主程序中使用。具体来说,使用Elements *直到ConjugationCheck :: checkConjugation步骤,并使用Molecule *直到程序结束。



主程序如下

  int main(int argc,char * argv []){
//初始化一个空数组来存储我们的分子。
vector< Molecule *> MyDataset;

//读取命令行输入。
InputReader * MyInputs = new InputReader();
if(!MyInputs-> readInputs(argc,argv)){delete MyInputs; return -1;}

//加载CMF文件。
CMFLoader * MyLoader = new CMFLoader(MyInputs);
unsigned int min_same_grp = MyLoader-> getmin(); //为结构
定义最少的相同哈米特组no if(!MyLoader-> loadFile(MyDataset)){delete MyLoader; delete MyInputs; return -1;}
delete MyLoader;

cout<< MyDataset.size()<< 分子负载 endl;

//删除过大的分子。
BigFilter * MyBigFilter = new BigFilter(MyInputs);
if(!MyBigFilter-> filterBigLigands(MyDataset)){delete MyBigFilter; delete MyInputs; return -1;}
delete MyBigFilter;

cout<< 在大配体过滤器之后留下的分子:< MyDataset.size()<< endl;

//标记在分子中发现的任何Hammetts基团。
HammettCheck * MyHammettCheck = new HammettCheck(min_same_grp);
if(!MyHammettCheck-> loadHammetts()){delete MyHammettCheck; delete MyInputs; return -1;}
如果(!MyHammettCheck-> checkHammett(MyDataset)){delete MyHammettCheck; return -1;}
delete MyHammettCheck;

cout<< 含有Hammett基团的分子:< MyDataset.size()<< endl;

ConjugationCheck * MyConjugationCheck = new ConjugationCheck(min_same_grp);
if(!MyConjugationCheck-> checkConjugation(MyDataset)){delete MyConjugationCheck; delete MyInputs; return -1;}
delete MyConjugationCheck;

cout<< 含有共轭Hammett基团的分子: MyDataset.size()<< endl;

DataAdder * MyDataAdder = new DataAdder(MyInputs);
if(!MyDataAdder-> addData(MyDataset)){delete MyDataAdder; delete MyInputs; return -1;}
delete MyDataAdder;

//根据NLOCompare给出的NLO评分对分子进行排序。
if(min_same_grp == 1){sort(MyDataset.begin(),MyDataset.end(),NLOCompare);}
else {sort(MyDataset.begin(),MyDataset.end OctuNLOCompare);}

//保存一个只包含预测的NLO分子的新CIF文件。
FileSaver * MyFileSaver = new FileSaver(MyInputs);
if(!MyFileSaver-> saveFile(MyDataset)){delete MyFileSaver; delete MyInputs; return -1;}
delete MyFileSaver;

/ *
保存可导入到Excel中的txt文件,显示分子中每个选定Hammett组的
路径。
* /
ExcelSaver * MyExcelSaver = new ExcelSaver(MyInputs);
if(!MyExcelSaver-> saveFile(MyDataset)){delete MyExcelSaver; delete MyInputs; return -1;}
delete MyExcelSaver;

//在退出程序之前清除内存。
for(unsigned int i = 0; i< MyDataset.size(); i ++){
delete MyDataset [i];
}
delete MyInputs;
return 0;
}

在程序的各个点,如果Molecule MyDataset [i]适合某些条件,它使用

删除使用

  MyDataset.pop_back 

所以这将调用Molecule Destructor,看起来像这样

  Molecule ::〜Molecule(void)
{
//删除分子中的所有原子。
for(unsigned int i = 0; i< mol_atoms.size(); i ++){
delete mol_atoms [i];
}

//删除分子中的所有键。
for(unsigned int i = 0; i< mol_bonds.size(); i ++){
delete mol_bonds [i];
}

//删除包含的元素类。
delete mol_formula;
}

我不知道这里出了什么问题。如何解决内存泄漏问题?



我的Valgrind Memcheck Leak摘要中的绝对丢失问题

  == 34809 == 2块中的400(96个直接,304间接)字节绝对丢失在丢失记录24中33 
== 34809 == at 0x1000A0679:malloc(vg_replace_malloc.c:266)
== 34809 == by 0x1000F7F04:operator new(unsigned long)(在/usr/lib/libstdc++.6.0.9.dylib)
== 34809 == by 0x10000A3B4:CMFLoader :: readMolecule(std :: basic_ifstream< char,std :: char_traits< char>& std :: string,Molecule *)(in ./OctuDiscovery)
== 34809 == by 0x10000B9EE:CMFLoader :: loadFile(std :: vector< Molecule *,std :: allocator< Molecule *>&)(in ./OctuDiscovery)
== 34809 == by 0x10000282E: main(in ./OctuDiscovery)

== 34809 == 1块中的12,833(152个直接,12,681个间接)字节在丢失记录中肯定丢失33 33
== 34809 ==在0x1000A0679:malloc(vg_replace_malloc.c:266)
== 34809 == by 0x1000F7F04:operator new(unsigned long)(在/usr/lib/libstdc++.6.0.9.dylib)
== 34809 == by 0x10000B93B:CMFLoader :: loadFile(std :: vector< Molecule *,std :: allocator< Molecule *> &)(in ./OctuDiscovery)
== 34809 == by 0x10000282E:main(in ./OctuDiscovery)


解决方案

比回答更多的评论,但是评论太长:

在下一个函数中,它没有意义使用动态内存:

  Molecule * CMFLoader :: readMolecule(ifstream& in_file,string id)
{
Molecule * my_mol = new Molecule(id);
//语句,沿着readFormula函数的某处被调用
my_mol-> setFormula(readFormula(ss));
return my_mol;
}

您可以将其替换为:

  Molecule CMFLoader :: readMolecule(ifstream& in_file,string id)
{
Molecule my_mol
//语句,沿着readFormula函数的某处调用
my_mol.setFormula(readFormula(ss));
return my_mol;
}

这解决了已经可能的内存泄漏,内存版本是必需的/首选,在这种情况下应该使用已经提到的unique_ptr。


In order to solve this problem Bad memory management? Class member (boolean) value greater than 1, in recursion function, I ran the whole program under Valgrind and found a few memory leak problems that occurred before the step. There were 2 'definitely lost' problems identified in the function CMFLoader.

(here MyDataset is a vector of Molecule objects, and each Molecule object contains an Elements object)

In CMFLoader::loadFile(vector& MyDataset), I originally have

MyDataset.push_back( readMolecule( in_file, word );

where CMFLoader::readMolecule returns a Molecule object. Within the readMolecule function, a new Molecule object is created (but not deleted until the very end of main, more on that later)

Molecule* CMFLoader::readMolecule( ifstream& in_file, string id)
{
Molecule* my_mol = new Molecule( id );
// statements, somewhere along the readFormula function is called
my_mol->setFormula( readFormula( ss ) );
return my_mol;
}

where CMFLoader::readFormula returns an Element object and there is a Molecule::setFormula function to save it to the Molecule object. In readFormula

Elements* CMFLoader::readFormula( stringstream& ss )
{
Elements* my_formula = new Elements();
...
return my_formula;
}

I ran into problems described in the question here, later in the main program. The specific problem occurred at the HammettCheck::checkHammett step. I then changed the above CMFLoader functions to something like this. The problems I encountered earlier seems to have disappeared (but there were other problems later in the program that were no doubt related to the memory leak):

in CMFLoader::loadFile

Molecule* new_mol = new Molecule(word);
    MyDataset.push_back( readMolecule( in_file, word ,new_mol) );

where readMolecule now takes in a new argument Molecule* and the new operator is removed within the function. Similarly, in readFormula, I now have

 Elements* new_formula = new Elements();
my_mol->setFormula( readFormula( ss, new_formula ) );

etc.

Now of course the memory leak problem is not removed! However, I cannot put in the delete operator within any of the CMFLoader functions as the objects are used later in the main program. Specifically, Elements* is used till the ConjugationCheck::checkConjugation step, and Molecule* is used till the program ends.

Main program goes like this

int main(int argc, char* argv[]){
//initialising an empty array to store our molecules.
vector<Molecule*> MyDataset;

//Read command line inputs.
InputReader* MyInputs = new InputReader();
if( !MyInputs->readInputs(argc, argv) ) {delete MyInputs;return -1;}

//Load CMF file.
CMFLoader* MyLoader = new CMFLoader( MyInputs );
unsigned int min_same_grp = MyLoader->getmin(); //define minimum no of same hammett groups for structure
if( !MyLoader->loadFile( MyDataset ) ) {delete MyLoader;delete MyInputs;return -1;}
delete MyLoader;

cout << MyDataset.size() << " molecules loaded" << endl;

//Remove molecules which are too large.
BigFilter* MyBigFilter = new BigFilter( MyInputs );
if( !MyBigFilter->filterBigLigands( MyDataset ) ) {delete MyBigFilter;delete MyInputs;return -1;}
delete MyBigFilter;

cout << "Molecules left after big ligand filter: " << MyDataset.size() << endl;

//Mark any Hammetts groups found in molecules.
HammettCheck* MyHammettCheck = new HammettCheck(min_same_grp);
if( !MyHammettCheck->loadHammetts() ) {delete MyHammettCheck;delete MyInputs;return -1;}
if( !MyHammettCheck->checkHammett( MyDataset ) ) {delete MyHammettCheck;delete MyInputs;return -1;}
delete MyHammettCheck;

cout << "Molecules containing Hammett Groups: " << MyDataset.size() << endl;

ConjugationCheck* MyConjugationCheck = new ConjugationCheck(min_same_grp);
if( !MyConjugationCheck->checkConjugation( MyDataset ) ) {delete MyConjugationCheck;delete MyInputs;return -1;}
delete MyConjugationCheck;

cout << "Molecules containing conjugated Hammett Groups: " << MyDataset.size() << endl;

DataAdder* MyDataAdder = new DataAdder( MyInputs );
if( !MyDataAdder->addData( MyDataset ) ) {delete MyDataAdder; delete MyInputs;return -1;}
delete MyDataAdder;

//Sorts molecules based on their NLO rating given by NLOCompare.
if (min_same_grp ==1) {sort(MyDataset.begin(), MyDataset.end(), NLOCompare);}
else {sort(MyDataset.begin(), MyDataset.end(), OctuNLOCompare);}

//Saves a new CIF file containing just the predicted NLO molecules.
FileSaver* MyFileSaver = new FileSaver( MyInputs );
if( !MyFileSaver->saveFile( MyDataset ) ) {delete MyFileSaver;delete MyInputs;return -1;}
delete MyFileSaver;

/*
Saves a txt file which can be imported into Excel, showing the
paths to each of the selected Hammett groups in a molecule.
*/
ExcelSaver* MyExcelSaver = new ExcelSaver( MyInputs );
if( !MyExcelSaver->saveFile( MyDataset ) ) {delete MyExcelSaver;delete MyInputs;return -1;}
delete MyExcelSaver;

//Cleans the memory before exiting the program.
for(unsigned int i=0; i < MyDataset.size(); i++){
    delete MyDataset[i];
}
delete MyInputs;
return 0;
}

At various points in the program, if the Molecule MyDataset[i] does not fit certain conditions, it is removed using

MyDataset.pop_back();

So this would call the Molecule Destructor, which looks like this

Molecule::~Molecule(void)
{
//Deletes all atoms in molecule.
for(unsigned int i=0; i < mol_atoms.size(); i++){
    delete mol_atoms[i];
}

//Deletes all bonds in molecule.
for(unsigned int i=0; i < mol_bonds.size(); i++){
    delete mol_bonds[i];
}

//Deletes the class of elements contained.
delete mol_formula;
}

I am not sure what went wrong here. How should I fix the memory leak problem?

The "definitely loss" problems in my Valgrind Memcheck Leak summary

==34809== 400 (96 direct, 304 indirect) bytes in 2 blocks are definitely lost in loss record 24 of 33
==34809==    at 0x1000A0679: malloc (vg_replace_malloc.c:266)
==34809==    by 0x1000F7F04: operator new(unsigned long) (in /usr/lib/libstdc++.6.0.9.dylib)
==34809==    by 0x10000A3B4: CMFLoader::readMolecule(std::basic_ifstream<char, std::char_traits<char> >&, std::string, Molecule*) (in ./OctuDiscovery)
==34809==    by 0x10000B9EE: CMFLoader::loadFile(std::vector<Molecule*, std::allocator<Molecule*> >&) (in ./OctuDiscovery)
==34809==    by 0x10000282E: main (in ./OctuDiscovery)

==34809== 12,833 (152 direct, 12,681 indirect) bytes in 1 blocks are definitely lost in loss record 33 of 33
==34809==    at 0x1000A0679: malloc (vg_replace_malloc.c:266)
==34809==    by 0x1000F7F04: operator new(unsigned long) (in /usr/lib/libstdc++.6.0.9.dylib)
==34809==    by 0x10000B93B: CMFLoader::loadFile(std::vector<Molecule*, std::allocator<Molecule*> >&) (in ./OctuDiscovery)
==34809==    by 0x10000282E: main (in ./OctuDiscovery)

解决方案

More a comment than an answer, but too long for a comment:
In next function, it doesn't make sense to use dynamic memory:

Molecule* CMFLoader::readMolecule( ifstream& in_file, string id)
{
Molecule* my_mol = new Molecule( id );
// statements, somewhere along the readFormula function is called
my_mol->setFormula( readFormula( ss ) );
return my_mol;
}

You could replace it with:

Molecule CMFLoader::readMolecule( ifstream& in_file, string id)
{
Molecule my_mol( id );
// statements, somewhere along the readFormula function is called
my_mol.setFormula( readFormula( ss ) );
return my_mol;
}

This solves already 1 possible memory leak, but there might be reasons why the dynamic memory version is needed/preferred, in which case the already mentioned unique_ptr should be used.

这篇关于在何处/如何删除另一个对象中的对象,在创建它的函数之外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆