C:双重免费或损坏,找不到错误

时间:2013-05-15 18:17:28

标签: c++ memory-leaks valgrind

这个错误让我很生气......

Valgrinding程序显示delete[](第40行)中的DataPackage::~DataPackage会产生问题。但如果我删除它,该程序将泄漏。 那么,如何修复它以及我做错了什么?

main.cxx

#include "main.h" // currently includes DataPackage.h only

DataPackage aTestFunction(){
  return DataPackage("hello",5);
}

int main(){
  DataPackage pack1 = aTestFunction(), pack2 = aTestFunction();
  pack1 = pack2;

  for(unsigned int i = 0; i < pack1.getLength(); i++){
    printf("0x%02x ", *(pack1.getData()+i)&0xff);
  }

  return 0;
}

DataPackage.cxx

#include "DataPackage.h" // defines only the class, and private members m_data (char*) and m_length (size_t), includes <cstdio> and <cstring>

DataPackage::DataPackage(){
  m_data = NULL;
  m_length = 0;
}

DataPackage::DataPackage(string data){
  m_data = NULL;
  setData(data.c_str(),data.length()+1);
}

DataPackage::DataPackage(const char *data, size_t length) {
  m_data = NULL;
  setData(data,length);
}

DataPackage::DataPackage(const DataPackage &pack) {
  m_data = NULL;
  setData(pack.m_data,pack.m_length);
}

const char* DataPackage::getData(){
  return m_data;
}

void DataPackage::setData(const char *newdata,size_t newlength){
  char* tmpdata = new char[newlength];
  m_length = newlength;
  memcpy(tmpdata,newdata,m_length);
  delete[] m_data;
  m_data = tmpdata;
}

size_t DataPackage::getLength(){
  return m_length;
}

DataPackage::~DataPackage() {
  delete[] m_data;
}

4 个答案:

答案 0 :(得分:3)

您忘记了Rule of Three,但没有提供复制赋值运算符。因此,当从另一个DataPackage分配一个std::string时,两者都会得到指向同一缓冲区的指针,并且都试图删除它。

我会抛弃那个课程而改为使用std::vector<char>或{{1}}。

答案 1 :(得分:1)

错误是由'pack1 = pack2;'引起的在main.cxx中

实施DataPackage :: operator =来修复它。

答案 2 :(得分:0)

您需要实现一个管理m_data的赋值运算符。自动生成的实现只会复制指针,而不是复制指向的数组。赋值运算符可能如下所示:

DataPackage& DataPackage::operator=(const DataPackage &other) {
   setData(other.m_data, other.m_length);
   return *this;
}

答案 3 :(得分:-1)

尝试:

void DataPackage::setData(const char *newdata,size_t newlength){
  char* tmpdata = new char[newlength];
  m_length = newlength;
  memcpy(tmpdata,newdata,m_length);

  if (m_data)
  {
      delete[] m_data;
  }

  m_data = tmpdata;
}

从我看到你的拷贝构造函数将m_data设置为NULL并在之后调用setData。在setData中你基本上是在做delete [] NULL;