C ++纯虚方法内存管理问题

时间:2011-04-09 20:19:50

标签: c++ inheritance memory-leaks valgrind

我有一个基类(此处为AClass),其protected资源(此处为str)在free析构函数中获得AClass'd 。派生BClass具有纯虚拟Init方法。派生CClass实现Init,为受保护资源分配一些内存。

Valgrind说我有3个分配和2个释放。老实说,我只是显式看到1个alloc和1个free,但我会接受有一些我看不到的(现在,但请有人解释)。但是,为什么他们至少不是平衡?每个派生的实例是否也拥有它自己的str并且它没有获得free'd?

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

class AClass;
class BClass;
class CClass;

class AClass
{
public:
  AClass() : str(NULL) {
    printf("AClass Constructor with no params.\n");
    str = (char *) malloc(5 * sizeof(char)); 
  }
  AClass(char *foo) {
    printf("AClass Constructor with params, %s.\n", foo);
  }
  virtual ~AClass () {
    printf("AClass Destructor. Getting ready to free %s\n", str);
    free(str);
    printf("\tfree.\n");
  }

protected:
  char *str;
};

class BClass : public AClass
{
public:
  BClass() {
    printf("BClass Constructor with no params.\n");
  };
  BClass(char *foo) : AClass(foo) {
    printf("BClass Constructor with params, %s.\n", foo);
    str = foo;
  };
  virtual void Init() = 0;
  virtual ~BClass () {
    printf("BClass Destructor.\n");
  };
};

class CClass : public BClass
{
public:
  CClass () {
    printf("CClass Constructor with no params.\n");
  };
  void Init() {
    printf("CClass Init method.\n");
    str = (char *) malloc(255 * sizeof(char));
    printf("\tmalloc.\n");
    snprintf(str, 255 * sizeof(char), "Hello, world.");
  };
  virtual ~CClass () {
    printf("CClass Destructor.\n");
  };
};

int main (int argc, char const *argv[])
{
  printf("Start.\n");
  BClass *x = new CClass();
  x->Init();
  delete x;
  printf("End.\n");
  return 0;
}

这是Valgrind的输出。

==6641== Memcheck, a memory error detector
==6641== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==6641== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==6641== Command: ./a.out
==6641==
Start.
AClass Constructor with no params.
BClass Constructor with no params.
CClass Constructor with no params.
CClass Init method.
        malloc.
CClass Destructor.
BClass Destructor.
AClass Destructor. Getting ready to free Hello, world.
        free.
End.
==6641==
==6641== HEAP SUMMARY:
==6641==     in use at exit: 5 bytes in 1 blocks
==6641==   total heap usage: 3 allocs, 2 frees, 268 bytes allocated
==6641==
==6641== LEAK SUMMARY:
==6641==    definitely lost: 5 bytes in 1 blocks
==6641==    indirectly lost: 0 bytes in 0 blocks
==6641==      possibly lost: 0 bytes in 0 blocks
==6641==    still reachable: 0 bytes in 0 blocks
==6641==         suppressed: 0 bytes in 0 blocks
==6641== Rerun with --leak-check=full to see details of leaked memory
==6641==
==6641== For counts of detected and suppressed errors, rerun with: -v
==6641== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 18 from 7)

3 个答案:

答案 0 :(得分:5)

当您构建Init CClass的{​​{1}}实例时,str指针首先会被指定malloc AClass来自malloc的指针默认构造函数,然后在CClass::Init中分配了来自AClass调用的指针。永远不会释放在str默认构造函数中分配的内存,并且在CClass::Init中覆盖str时指针会丢失。

您可以在CClass::Init指针中检查非NULL值,然后在str中重新分配它。或者,您可以将void allocate_str(int size) { if (str) free(str); str = (char*) malloc(size * sizeof(char)); } 赋值封装在执行此检查的成员函数中,以便在其他地方不会出现此问题:

{{1}}

更好的是,您可以利用C ++运行时库的许多现代功能,包括字符串对象和智能指针。

答案 1 :(得分:5)

这与虚拟功能没有任何关系。 Valgrind检测到的三个分配是:

    {li> new CClass main。 在malloc构造函数中
  1. AClass
  2. {li> malloc CClass::Init

    至于调用不平衡的原因:您在str构造函数中泄漏了AClass - 您正在更改str CClass::Init指针:

    void Init() {
        // ...
        str = (char *) malloc(255 * sizeof(char));
        // ...
    };
    

    没有先释放先前分配的缓冲区。

答案 2 :(得分:2)

AClass默认构造函数有这一行:

 str = (char *) malloc(5 * sizeof(char)); // hey, 5 bytes!

在您的初始化版中,当您执行此操作时会丢失它

 str = (char *) malloc(255 * sizeof(char));

第三个alloc(和第二个免费)是新的和删除的CClass