【问题标题】:Error: *** glibc detected *** w5: double free or corruption (fasttop):错误:***检测到 glibc *** w5:双重释放或损坏(fasttop):
【发布时间】:2014-02-17 04:49:38
【问题描述】:

这是我得到的错误:

======= Memory map: ========
08048000-0804a000 r-xp 00000000 00:28 2955225621  /home/w5/w5
...more
Aborted

我的程序编译完美,我的部分输出也是正确的。 我有 3 个文件,w5.cpp、employee.h、employee.cpp。 我需要创建一个复制构造函数、一个赋值运算符和一个析构函数。

w5.cpp(有点大)。 http://hostcode.sourceforge.net/view/1435.txt

员工.h 类员工{

   int empNum;
   char* empName;

   public:
     //Constructor 
      Employee();
      Employee(int num, const char* name);

     //Copy Constructor
      Employee(const  Employee& source);

     //Assignment operator
      Employee& operator=(const Employee& source);

     //Destructor
      ~Employee();

      void display() const;
      bool isGreaterThan(const Employee&) const;

};

员工.cpp

#include <iostream>
using namespace std;
#include "Employee.h"
#include <string.h>

Employee::Employee() {
   empNum = 0;
   empName= nullptr;
}
Employee::Employee(int num, const char* name) {

   if(num < 0 || strcmp(name,"")==0) {
      Employee();
   } 
   else {
      empNum = num;
      empName = new char[strlen(name)+1];
      strcpy(empName, name);
   }
}

Employee::Employee(const Employee& source) {

   cout << "Copy Constructor!"<<endl;

   if(source.empName !=nullptr) {
      empNum = source.empNum;
      empName = new char[strlen(source.empName)+1];
      //strcpy(empName, source.empName);
      empName = source.empName;
   }
   else 
      empName =nullptr;
}

Employee& Employee::operator=(const Employee& source) {

   cout << "Operator Assignment!" <<endl;          

   // check for self-assignment
   if(this != &source) {
       cout << "Operator Assignment 2" <<endl;

      empNum = source.empNum;
      delete [] empName;
      if(source.empName !=nullptr) { 
         empName = source.empName;
         //strcpy(empName, source.empName);
      }
      else
         empName = nullptr;
   }
   return *this;
}

//Destructor
Employee::~Employee() {
   delete [] empName;                     
}

void Employee::display() const {

   cout << empNum << empName <<endl;
}

bool Employee::isGreaterThan(const Employee& source) const {

   return true;
   //still need to code here
}

为了编译这个我使用g++ -std=c++0x -o w5 w5.cpp Employee.cpp 在网上查看这个问题后,我认为我有一个“无效指针”,但我不确定在哪里。

【问题讨论】:

    标签: c++ copy-constructor assignment-operator


    【解决方案1】:

    我看到的一个问题是您的赋值运算符:

    // these two lines should be removed
    empNum = source.empNum;
    delete [] empName; // this deletes the source's employee name! (bad)
    
    if (source.empName != nullptr) { 
         empName = source.empName;
    }
    

    您不应该只将对象的empName 指针分配给source 分配的内存,因为source 将在调用析构函数时删除该内存。您应该为字符串分配新内存,然后复制到其中:

    // first delete our string if we've previously allocated memory for it
    if (empName != nullptr) {
        delete [] empName;
        empName = nullptr;
    }
    
    // now copy the source's empName
    if (source.empName != nullptr) { 
         empName = new char[strlen(source.empName)+1];
         strcpy(empName, source.empName);
    }
    

    【讨论】:

    • 如果我使用 strcpy() 我得到分段错误
    • 因为你没有在 operator= 中为 empName 分配内存
    • 我最初说的是“复制构造函数”,但实际上是赋值运算符有问题。如果您首先按照我上面的说明分配内存,那么它不应该出现段错误。
    • 哦,是的,现在分段错误消失了。但由于某种原因,我无法输出 empName。显示功能。
    • 它有显示的价值吗?你说不能输出是什么意思?
    【解决方案2】:

    改回strcpy:

    empName = source.empName;
    

    否则你会双重释放这个指针

    您的复制构造函数也正确分配内存,而 operator= 没有。

    【讨论】:

      【解决方案3】:

      在复制构造函数中,我们应该创建所有指针的副本。

      Employee::Employee(const Employee& source) {
      
         cout << "Copy Constructor!"<<endl;
      
         if(source.empName !=nullptr) {
            empNum = source.empNum;
            empName = new char[strlen(source.empName)+1];
            //strcpy(empName, source.empName);
            empName = source.empName;
         }
         else 
            empName =nullptr;
      } 
      

      行“empName = source.empName;”将导致对象的 empName 以及 src 对象的 empName 指向相同的位置。内存也泄露了。

      在赋值运算符中你也有同样的问题。分配内存后,不要分配指针执行 strcpy 或 memcpy 。在释放它之前还要检查指针值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        相关资源
        最近更新 更多