繁体   English   中英

在创建对象的功能之外的其他对象中删除对象的位置/方式

[英]Where/how to delete an object within another object, outside the function that it was created in

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

(此处MyDataset是分子对象的向量,每个分子对象都包含一个Elements对象)

在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 );
// statements, somewhere along the readFormula function is called
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 *,并且在该函数中删除了新的运算符。 同样,在readFormula中,我现在有

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

等等

现在,当然不能解决内存泄漏问题! 但是,我无法在任何CMFLoader函数中放入delete运算符,因为稍后将在主程序中使用这些对象。 具体来说,将使用Elements *直到ConjugationCheck :: checkConjugation步骤为止,并使用Molecule *直到程序结束为止。

主程序是这样的

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

在程序的各个点上,如果Molecule MyDataset [i]不满足某些条件,则使用以下命令将其删除

MyDataset.pop_back();

所以这叫做分子破坏子,看起来像这样

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

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

我的Valgrind Memcheck泄漏摘要中的“绝对损失”问题

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

评论多于答案,但评论太长:
在下一个函数中,使用动态内存没有意义:

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

您可以将其替换为:

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

这样已经解决了1种可能的内存泄漏,但是可能由于某些原因需要/首选动态内存版本,在这种情况下,应使用已经提到的unique_ptr。

如果您想做这样的事情,我建议您看一下std :: auto_ptr类,或者至少看一下智能指针或自动指针的概念。 您应该依赖RAII(资源获取即初始化)范式,这意味着内存管理应由对象自己完成:尽可能避免使用基本指针和自写的内存管理代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM