C++ 在何处/如何删除创建对象的函数之外的另一个对象中的对象
为了解决这个问题,我在Valgrind下运行了整个程序,并发现了在该步骤之前发生的一些内存泄漏问题。在功能CMFLoader中发现了2个“肯定丢失”的问题 (这里MyDataset是分子对象的向量,每个分子对象包含一个Elements对象) 在CMFLoader::loadFile(vector&MyDataset)中,我最初有C++ 在何处/如何删除创建对象的函数之外的另一个对象中的对象,c++,object,memory,memory-leaks,delete-operator,C++,Object,Memory,Memory Leaks,Delete Operator,为了解决这个问题,我在Valgrind下运行了整个程序,并发现了在该步骤之前发生的一些内存泄漏问题。在功能CMFLoader中发现了2个“肯定丢失”的问题 (这里MyDataset是分子对象的向量,每个分子对象包含一个Elements对象) 在CMFLoader::loadFile(vector&MyDataset)中,我最初有 MyDataset.push_back( readMolecule( in_file, word ); 其中CMFLoader::readMolecule返回一个Mo
MyDataset.push_back( readMolecule( in_file, word );
其中CMFLoader::readMolecule返回一个Molecule对象。在readmolecle函数中,创建了一个新的molecle对象(但直到main的末尾才删除,稍后将详细介绍)
其中,CMFLoader::readFormula返回一个元素对象,并且有一个Molecule::setFormula函数将其保存到Molecule对象。在readFormula中
Elements* CMFLoader::readFormula( stringstream& ss )
{
Elements* my_formula = new Elements();
...
return my_formula;
}
我遇到了问题中描述的问题,稍后在主程序中。具体问题发生在HammetCheck::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 ) );
等等
当然,现在内存泄漏问题还没有解决!但是,I无法在任何CMFLoader函数中输入delete运算符,因为这些对象稍后将在主程序中使用。具体来说,元素*一直使用到共轭Check::checkConjugation步骤,分子*一直使用到程序结束
主程序是这样的
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::~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;
}
这就叫分子析构函数,看起来像这样
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::~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;
}
分子::~分子(空)
{
//删除分子中的所有原子。
for(无符号整数i=0;i
我不确定这里出了什么问题。如何解决内存泄漏问题?
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)
==34809==400(96个直接字节,304个间接字节)两个块中的字节肯定会在33个块中的24个丢失记录中丢失
==34809==0x1000A0679:malloc(vg_替换_malloc.c:266)
==34809==by 0x1000F7F04:运算符新(无符号长)(in/usr/lib/libstdc++.6.0.9.dylib)
==34809==0x10000A3B4:CMFLoader::readMolecule(std::basic_ifstream&,std::string,Molecule*)(in./OctuDiscovery)
==34809==by 0x10000B9EE:CMFLoader::loadFile(std::vector&)(in./OctuDiscovery)
==34809==0x10000282E:main(in./OctuDiscovery)
==34809==12833(152个直接字节,12681个间接字节)1个块中的字节肯定会在33个块中的丢失记录33中丢失
==34809==0x1000A0679:malloc(vg_替换_malloc.c:266)
==34809==by 0x1000F7F04:运算符新(无符号长)(in/usr/lib/libstdc++.6.0.9.dylib)
==34809==0x10000B93B:CMFLoader::loadFile(std::vector&)(in./OctuDiscovery)
==34809==0x10000282E:main(in./OctuDiscovery)
如果您想做这样的事情,我建议您看看std::auto_ptr类,或者至少看看智能指针或自动指针的概念。您应该依赖RAII(Resource Aquisition Is Initialization)范式,这意味着内存管理应该由对象本身完成:尽可能避免使用基本指针和自行编写的内存管理代码 如果您想做这样的事情,我建议您看看std::auto_ptr类,或者至少看看智能指针或自动指针的概念。您应该依赖RAII(Resource Aquisition Is Initialization)范式,这意味着内存管理应该由对象本身完成:尽可能避免使用基本指针和自行编写的内存管理代码 与其说是回答,不如说是评论,但评论太长:在下一个函数中,使用动态内存没有意义:
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个可能的内存泄漏问题,但可能有需要/首选动态内存版本的原因,在这种情况下,应该使用已经提到的唯一\u ptr。与其说是答案,不如说是注释:
在下一个函数中,使用动态内存没有意义:
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\u ptr。这需要大量的
delete
so\o。您应该阅读RAII,特别是unique\u ptr
。所有资源都应该由负责其生命周期的自动对象拥有。使用类型系统确保没有任何泄漏。@Mankarse我看到unique_ptr是c++11实现?如果我使用的是gcc4.2编译器,我应该改用auto_ptr吗?@幻灭:您可以使用auto_ptr
,或者您可以使用,或者您可以使用自己的unique_ptr
,或者您可以停止对尽可能多的事情使用动态分配——您在main
中构造的任何对象都完全不需要它,例如(或者你所展示的代码中的任何地方),同样,你在最后说,从向量
上弹出一个分子*
将调用它的析构函数。我敢肯定不会的。如果它是一个向量
,它就会出现。这很可能是导致内存泄漏的原因。@dogmative所以,如果我先调用析构函数,然后再弹出向量,这可能会解决我的问题吗?说replace MyDataset.pop_back();使用delete MyDataset[i];MyDataset.erase(MyDataset