释放内存时出错
Error freeing memory
当我将带有动态内存的自定义 class 添加到向量中时,出现了一个奇怪的错误。
错误是
error for object 0x7fee9ac000e0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
尝试使用动态内存添加 Symbol
会产生错误,在析构函数中删除 delete[] parameters
会删除错误,但我认为会导致内存泄漏。
代码如下
//test.cpp
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "symbol.h"
int main(int argc, char const *argv[])
{
Symbol a('A');
std::cout << a << std::endl;
Symbol b('B',2);
std::cout << b << std::endl;
double p[3] = {1.2, 2.4, 4.8};
Symbol c('C',3,p);
std::cout << c << std::endl;
Symbol* d = new Symbol('D',3,p);
////
std::cout << *d << std::endl;
std::vector<Symbol> axiom;
axiom.push_back(a)
axiom.push_back(b); // This lines produces the error
delete d;
return 0;
}
//symbol.h
#ifndef SYMBOL_H
#define SYMBOL_H
#include <iostream>
class Symbol{
friend std::ostream& operator<<(std::ostream& output, const Symbol& s);
private:
char character;
int numpar;
double* parameters;
public:
Symbol();
Symbol(const char c);
Symbol(const char c, const int n);
Symbol(const char c, const int n, const double p[]);
~Symbol();
bool operator == (const Symbol &other) const;
};
#endif
//symbol.cpp
#include "symbol.h"
Symbol::Symbol()
{
character = 0;
numpar = 0;
}
Symbol::Symbol(const char c)
{
character = c;
numpar = 0;
}
Symbol::Symbol(const char c, const int n)
{
character = c;
if(n > 0)
{
numpar = n;
parameters = new double[numpar];
std::fill(parameters, parameters+numpar, 0.0);
}
else
{
numpar = 0;
}
}
Symbol::Symbol(const char c, const int n, const double p[])
{
character = c;
if(n > 0)
{
numpar = n;
parameters = new double[numpar];
std::copy(p,p+numpar,parameters);
}else{
numpar = 0;
}
}
Symbol::~Symbol()
{
if(this->numpar > 0)
{
delete[] parameters; //If I comment this line the code runs smoothly but I think it produces memory leaks
}
}
bool Symbol::operator==(const Symbol &other) const {
if (character == other.character)
return true;
return false;
}
std::ostream& operator<<(std::ostream& output, const Symbol &s){
output << s.character;
if(s.numpar > 0)
{
output << '(';
for(int i = 0 ; i < s.numpar-1 ; i++)
{
output << s.parameters[i] << ", ";
}
output << s.parameters[s.numpar-1] << ')';
}
return output;
}
您使用的是矢量< Symbol >,因此当您 push_back 一个 Symbol 时,它实际上创建了一个新的 Symbol,并且由于您没有定义复制构造函数,它只是复制字段而不询问任何内容。
所以你实际上有两个 Symbol 实例,它们的指针指向同一个参数数组,当一个被销毁时,另一个尝试释放已经释放的东西。
参见:http://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm
当您将持有动态内存的 Symbol
实例存储到向量中时:
axiom.push_back(b);
已复制。由于您尚未声明自己的复制构造函数,默认复制构造函数将复制所有成员,因此现在两个实例拥有相同的 double* parameters
指针,并且它们最终都会尝试 delete[]
它。
如果您改用 std::vector<double> parameters
,默认的复制构造函数将依赖于 vector 的复制构造函数,这将做正确的事情
™.
一般来说,最好依靠标准库类型来为您处理所有权问题。
当我将带有动态内存的自定义 class 添加到向量中时,出现了一个奇怪的错误。
错误是
error for object 0x7fee9ac000e0: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug
尝试使用动态内存添加 Symbol
会产生错误,在析构函数中删除 delete[] parameters
会删除错误,但我认为会导致内存泄漏。
代码如下
//test.cpp
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "symbol.h"
int main(int argc, char const *argv[])
{
Symbol a('A');
std::cout << a << std::endl;
Symbol b('B',2);
std::cout << b << std::endl;
double p[3] = {1.2, 2.4, 4.8};
Symbol c('C',3,p);
std::cout << c << std::endl;
Symbol* d = new Symbol('D',3,p);
////
std::cout << *d << std::endl;
std::vector<Symbol> axiom;
axiom.push_back(a)
axiom.push_back(b); // This lines produces the error
delete d;
return 0;
}
//symbol.h
#ifndef SYMBOL_H
#define SYMBOL_H
#include <iostream>
class Symbol{
friend std::ostream& operator<<(std::ostream& output, const Symbol& s);
private:
char character;
int numpar;
double* parameters;
public:
Symbol();
Symbol(const char c);
Symbol(const char c, const int n);
Symbol(const char c, const int n, const double p[]);
~Symbol();
bool operator == (const Symbol &other) const;
};
#endif
//symbol.cpp
#include "symbol.h"
Symbol::Symbol()
{
character = 0;
numpar = 0;
}
Symbol::Symbol(const char c)
{
character = c;
numpar = 0;
}
Symbol::Symbol(const char c, const int n)
{
character = c;
if(n > 0)
{
numpar = n;
parameters = new double[numpar];
std::fill(parameters, parameters+numpar, 0.0);
}
else
{
numpar = 0;
}
}
Symbol::Symbol(const char c, const int n, const double p[])
{
character = c;
if(n > 0)
{
numpar = n;
parameters = new double[numpar];
std::copy(p,p+numpar,parameters);
}else{
numpar = 0;
}
}
Symbol::~Symbol()
{
if(this->numpar > 0)
{
delete[] parameters; //If I comment this line the code runs smoothly but I think it produces memory leaks
}
}
bool Symbol::operator==(const Symbol &other) const {
if (character == other.character)
return true;
return false;
}
std::ostream& operator<<(std::ostream& output, const Symbol &s){
output << s.character;
if(s.numpar > 0)
{
output << '(';
for(int i = 0 ; i < s.numpar-1 ; i++)
{
output << s.parameters[i] << ", ";
}
output << s.parameters[s.numpar-1] << ')';
}
return output;
}
您使用的是矢量< Symbol >,因此当您 push_back 一个 Symbol 时,它实际上创建了一个新的 Symbol,并且由于您没有定义复制构造函数,它只是复制字段而不询问任何内容。
所以你实际上有两个 Symbol 实例,它们的指针指向同一个参数数组,当一个被销毁时,另一个尝试释放已经释放的东西。
参见:http://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm
当您将持有动态内存的 Symbol
实例存储到向量中时:
axiom.push_back(b);
已复制。由于您尚未声明自己的复制构造函数,默认复制构造函数将复制所有成员,因此现在两个实例拥有相同的 double* parameters
指针,并且它们最终都会尝试 delete[]
它。
如果您改用 std::vector<double> parameters
,默认的复制构造函数将依赖于 vector 的复制构造函数,这将做正确的事情
™.
一般来说,最好依靠标准库类型来为您处理所有权问题。