簡體   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