【问题标题】:C++ glibc double-free errorC++ glibc 双释放错误
【发布时间】:2016-04-18 20:01:05
【问题描述】:

我遇到了一个我无法弄清楚的奇怪错误。我正在为考试而学习,所以我使用的是结构而不是类,因为这就是我们在课堂上所做的。这是我的代码

#include <iostream>
#include <string>
using namespace std;


struct Course;
ostream &operator<<(ostream &os, Course c);


struct Course {
        string name;
        Course(string n) {
                name = n;
        }
        Course(const Course &c) {
                cout << "Copying course" << endl;
                name = c.name;
        }
        Course &operator=(const Course &c) {
                cout << "Assigning course" << endl;
                name = c.name;
                return *this;
        }
};


struct Student {
        int id;
        Course *courses[5];
        int size;
        Student(int num) {
                id = num;
                for (int i = 0; i < 5; i++) {
                        courses[i] = new Course("Course");
                }
                size = 0;
        }
        Student(const Student &s) {
                cout << "Copying student" << endl;
                id = s.id;
                for (int i = 0; i < 5; i++) {
                        Course *temp = new Course(s.courses[i]->name);
                        courses[i] = temp;
                }
        }
        Student &operator=(const Student &s) {
                cout << "Assigning student" << endl;
                id = s.id;
                for (int i = 0; i < 5; i++) {
                        courses[i] = s.courses[i];
                }
                return *this;
        }
        ~Student() {
                for (int i = 0; i < 5; i++) {
                        delete courses[i];
                }
        }
        void print() {
                cout << id << ": " << endl;
                for (int i = 0; i < 5; i++) {
                        cout << courses[i]->name << endl;
                }
        }
        void addCourse(Course *c) {
                delete courses[size];
                courses[size] = c;
                size++;
        }
};

ostream &operator<<(ostream &os, Course *c) {
        return os << c->name << endl;
}

int main() {
        Student one(2342134);
        Course cs246("cs246");
        Course cs245("cs245");
        one.addCourse(&cs246);
        one.addCourse(&cs245);
        one.print();
        Student two = one;
        two.print();
}

这是错误

2342134:
cs246
cs245
Course
Course
Course
Copying student
2342134:
cs246
cs245
Course
Course
Course
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0000000000cd8db0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7db26)[0x7f359a7ddb26]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(_ZNSsD1Ev+0x40)[0x7f359adf87c0]
./a.out[0x40111e]
./a.out[0x401152]
./a.out[0x400dc7]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f359a78176d]
./a.out[0x400b89]
======= Memory map: ========
00400000-00402000 r-xp 00000000 00:34 45960378                           /u3/z38ahmed/cs246/1161/exam/2.22_Object/2.22.5_Copy-Constructor-and-Assignment/a.out
00601000-00602000 r--p 00001000 00:34 45960378                           /u3/z38ahmed/cs246/1161/exam/2.22_Object/2.22.5_Copy-Constructor-and-Assignment/a.out
00602000-00603000 rw-p 00002000 00:34 45960378                           /u3/z38ahmed/cs246/1161/exam/2.22_Object/2.22.5_Copy-Constructor-and-Assignment/a.out
00cc7000-00cf9000 rw-p 00000000 00:00 0                                  [heap]
7f359a460000-7f359a55b000 r-xp 00000000 fc:00 915519                     /lib/x86_64-linux-gnu/libm-2.15.so
7f359a55b000-7f359a75a000 ---p 000fb000 fc:00 915519                     /lib/x86_64-linux-gnu/libm-2.15.so
7f359a75a000-7f359a75b000 r--p 000fa000 fc:00 915519                     /lib/x86_64-linux-gnu/libm-2.15.so
7f359a75b000-7f359a75c000 rw-p 000fb000 fc:00 915519                     /lib/x86_64-linux-gnu/libm-2.15.so
7f359a760000-7f359a914000 r-xp 00000000 fc:00 915563                     /lib/x86_64-linux-gnu/libc-2.15.so
7f359a914000-7f359ab13000 ---p 001b4000 fc:00 915563                     /lib/x86_64-linux-gnu/libc-2.15.so
7f359ab13000-7f359ab17000 r--p 001b3000 fc:00 915563                     /lib/x86_64-linux-gnu/libc-2.15.so
7f359ab17000-7f359ab19000 rw-p 001b7000 fc:00 915563                     /lib/x86_64-linux-gnu/libc-2.15.so
7f359ab19000-7f359ab1e000 rw-p 00000000 00:00 0
7f359ab20000-7f359ab36000 r-xp 00000000 fc:00 914560                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f359ab36000-7f359ad35000 ---p 00016000 fc:00 914560                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f359ad35000-7f359ad36000 r--p 00015000 fc:00 914560                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f359ad36000-7f359ad37000 rw-p 00016000 fc:00 914560                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f359ad38000-7f359ae3a000 r-xp 00000000 fc:00 396701                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f359ae3a000-7f359b039000 ---p 00102000 fc:00 396701                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f359b039000-7f359b041000 r--p 00101000 fc:00 396701                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f359b041000-7f359b043000 rw-p 00109000 fc:00 396701                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f359b043000-7f359b046000 rw-p 00000000 00:00 0
7f359b048000-7f359b06a000 r-xp 00000000 fc:00 915535                     /lib/x86_64-linux-gnu/ld-2.15.so
7f359b268000-7f359b26a000 rw-p 00000000 00:00 0
7f359b26a000-7f359b26b000 r--p 00022000 fc:00 915535                     /lib/x86_64-linux-gnu/ld-2.15.so
7f359b26b000-7f359b26d000 rw-p 00023000 fc:00 915535                     /lib/x86_64-linux-gnu/ld-2.15.so
7f359b26d000-7f359b274000 rw-p 00000000 00:00 0
7ffdfdac4000-7ffdfdae5000 rw-p 00000000 00:00 0                          [stack]
7ffdfdb78000-7ffdfdb7a000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

我不知道 glibc 是什么意思,但我不知道我在哪里进行双重释放。当我注释掉 Student 析构函数时,代码可以正常工作。这是为什么?我为每门课程分配了内存,所以我在析构函数中释放了内存,所以我认为没有它程序就无法工作,但确实如此。 编辑:还有一件事。当我注释掉 Student two = one; 时并没有什么不同。行,所以我猜测错误在 addCourse() 和/或析构函数中

抱歉,这个问题太长了 非常感谢所以

【问题讨论】:

  • "所以我使用的是结构而不是类" 这里有一点 C++ 的乐趣:C++ 中没有 structs。我是认真的。 struct 只是创建一个 class ,其中所有内容都是 public ,除非另有声明。

标签: c++ glibc double-free


【解决方案1】:

你的赋值运算符有问题:

   Student &operator=(const Student &s) {
            cout << "Assigning student" << endl;
            id = s.id;
            for (int i = 0; i < 5; i++) {
                    courses[i] = s.courses[i];
            }
            return *this;
    }

您复制原始指针而不是对象,然后 2 个单独的 Student 对象拥有相同的 Course 对象,因此第二个 Student 的析构函数@ 相同的 Course 第二次被销毁。可能你想要:

  *(courses[i]) = *(s.courses[i]);

改为。

【讨论】:

  • 谢谢。我会改变的
【解决方案2】:

正如其他答案所指出的,您的赋值运算符不正确。

但是要轻松解决您的问题,只需使用 copy / swap,因为您已经为您的类编写了复制构造函数和析构函数:

#include <algorithm>
//...
Student &operator=(const Student &s) 
{
   cout << "Assigning student" << endl;
   Student temp(s);
   std::swap(temp.id, id);
   std::swap(temp.courses, courses);
   return *this;
}

我们刚刚从传入的Student 创建了一个临时的Student 副本,然后将当前学生的内部成员替换为临时的。同样,这只能与Student(您已经提供)的工作副本构造函数和析构函数一起使用。


另一个问题是addCourse 函数。问题是你给它的指针是 not 动态分配的对象。当调用析构函数时,它假定所有指针都来自对new 的调用,而实际上并非如此。

 void addCourse(Course *c) {
        delete courses[size];
        courses[size] = c;
        size++;
    }

~Student() {
    for (int i = 0; i < 5; i++) {
        delete courses[i];  // <-- Assumes all courses were allocated dynamically
    }
}

//...

Course cs246("cs246");
Course cs245("cs245");
one.addCourse(&cs246); // <-- Not allocated with new
one.addCourse(&cs245); // <-- Not allocated with new

这是您设计中的缺陷。要么通过对main 大喊大叫来禁止这一点

别这样,我只拿new"分配的东西,有这个代码:

Course* cs246 = new Course("cs246");
Course* cs245 = new Course("cs245");
one.addCourse(cs246);
one.addCourse(cs245);

Live Example

通过参考学习课程并复制它们(类似于vector的工作方式)并在课堂上自己管理记忆。

void addCourse(const Course& c) 
{
    delete courses[size];
    Course* temp = new Course(c);
    courses[size] = temp;
    size++;
}

//...

Course cs246("cs246");
Course cs245("cs245");
one.addCourse(cs246);
one.addCourse(cs245);

Live Example

【讨论】:

  • 谢谢。但是,我认为问题出在 addCourse() 函数中。当我注释掉学生时,二 = 一;和两个.print();行,我仍然得到错误。所以我猜测复制构造函数和赋值运算符不是导致错误的原因。
  • 查看我的编辑。您的班级假定所有课程都不是动态分配的。
  • 谢谢。有用。只是为了确认,只能在用 new 初始化的指针上调用 delete,而不仅仅是任何指针。对吗?
  • 是的,就是这样。
【解决方案3】:

Student &amp;operator=(const Student &amp;s) 中,您正在从s 复制指向课程的指针,因此您会得到双重删除。

我相信,为了完成作业,您可以像在复制构造函数中那样做 - 创建具有相同名称的新课程。

【讨论】:

  • 我更改了 operator=() 函数,但仍然出现该错误。我认为错误与复制构造函数有关,因为这是添加课程时调用的内容
猜你喜欢
  • 2013-12-04
  • 2014-11-10
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
相关资源
最近更新 更多