c++ 如何在使用继承和多态时安全地释放内存?

o8x7eapl  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(137)

我不知道如何在下面的代码示例中正确释放obj2,我尝试使用虚拟析构函数,但由于char指针m_s没有被分配,引发了异常。

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. private:
  6. char *m_s;
  7. public:
  8. A() { m_s = strdup("default"); }
  9. A(char *s) { del_data(); m_s = strdup(s); }
  10. A(const A& a) { del_data(); m_s = strdup(a.m_s); }
  11. virtual void prepare() { cout << "A "; }
  12. void display() {
  13. prepare();
  14. cout << m_s << endl;
  15. }
  16. void del_data()
  17. {
  18. if (m_s)
  19. {
  20. free(m_s);
  21. }
  22. m_s = nullptr;
  23. }
  24. virtual ~A()
  25. {
  26. del_data();
  27. }
  28. };
  29. class B : public A
  30. {
  31. public:
  32. B(char *s) : A(s) { }
  33. B(const B &b) : A(b){}
  34. void prepare() { cout << "B "; }
  35. ~B() {
  36. A::del_data();
  37. }
  38. };
  39. void foo(A *obj1, A obj2) {
  40. obj1->display();
  41. obj2.display();
  42. }
  43. int main() {
  44. B obj1("text");
  45. A *obj2 = new B(obj1);
  46. foo(&obj1, *obj2);
  47. delete obj2;
  48. return 0;
  49. }

当我删除obj2时,应该调用类B的析构函数,并且del_data()方法应该释放分配的内存并将m_s设置为nullptr。不知何故,它并不像预期的那样工作,我甚至尝试使用delete[]也无济于事。
我很想知道我做错了什么,以及如何在未来避免这种错误。
谢谢你的时间。

xxslljrj

xxslljrj1#

你的代码中有很多问题,但是segfault来自于m_s没有被初始化,因此你在一个随机地址上调用了del_data。与稳定性和正确覆盖虚函数有关的其他问题。你不需要像以前那样实现~B()~A()将被自动调用。
然而,在设计方面,您正在使用类似C的字符串API。我强烈建议使用std::string,这样在这种情况下会保存很多麻烦。
下面用C字符串修复。我把转换到std::string作为练习留给你;)

  1. #include <iostream>
  2. #include <string.h>
  3. using namespace std;
  4. class A
  5. {
  6. private:
  7. char *m_s = nullptr;
  8. public:
  9. A() { m_s = strdup("default"); }
  10. A(char const * const s) { del_data(); m_s = strdup(s); }
  11. A(const A& a) { del_data(); m_s = strdup(a.m_s); }
  12. virtual void prepare() const { cout << "A "; }
  13. void display() {
  14. prepare();
  15. cout << m_s << endl;
  16. }
  17. void del_data()
  18. {
  19. if (m_s)
  20. {
  21. free(m_s);
  22. }
  23. m_s = nullptr;
  24. }
  25. virtual ~A()
  26. {
  27. del_data();
  28. }
  29. };
  30. class B : public A
  31. {
  32. public:
  33. B(char const * const s) : A(s) { }
  34. B(const B &b) : A(b){}
  35. // override virtual prepare()
  36. void prepare() const override { cout << "B "; }
  37. ~B() =default;
  38. };
  39. void foo(A *obj1, A obj2) {
  40. obj1->display();
  41. obj2.display();
  42. }
  43. int main() {
  44. B obj1("text");
  45. A *obj2 = new B(obj1);
  46. foo(&obj1, *obj2);
  47. delete obj2;
  48. return 0;
  49. }

Live

展开查看全部
nkhmeac6

nkhmeac62#

如果在构造函数中调用的del_data()是用未初始化的m_s调用的(其值未指定)初始化为nullptr将修复它。

  1. class A
  2. {
  3. private:
  4. char *m_s = nullptr;
  5. ...

但是没有理由在构造函数中调用它-它永远不会指向必须释放的内存。

相关问题