首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

坛友们,这段代码能内存泄露

2013-09-06 
坛友们,这段代码会内存泄露?如下代码,delete pa以后,内存泄露吗?欢迎讨论^_^class A{public:A(){}virtual

坛友们,这段代码会内存泄露?
如下代码,delete pa;以后,内存泄露吗?欢迎讨论^_^

class A
{
public:
    A(){}
    virtual void f(){}

private:
    int m_a;
};

class B : public A
{
public:
    virtual void f(){}
private:
    int m_b;
};

int main()
{
A *pa = new B;
delete pa;
pa = NULL;

return 0;
}
[解决办法]

引用:
会,因为sizeof(A)=8,而sizeof(B)=12;

而A的析构函数不是虚函数,那么delete pa; 只会调用A的默认析构函数,释放8个字节内存,还有4字节内存泄露了。


析构函数是free()之前的调用,而真正释放内存的操作是free(void *ptr),
注意只有指针一个参数,没有长度参数,这说明了什么?
说明了 A *pa = new B;时带着长度sizeof(B)最终调用了malloc(sizeof(B));
申请的内存及长度已经被记录,当free(pa)是就会释放掉自pa开始长度为sizeof(B)
的内存。析构函数仅仅是应用逻辑层次的释放资源,不是物理层次的释放资源。
[解决办法]
不会,没析构这样delete安全,这里delete正如15L说的相当于free,删除已申请连续空间,和指针类型无关,
就算你用char*来代替也没事,
只有当有析构函数时且析构函数不是虚函数,这样delete才会泄露,当然要保证类结构本身不泄露情况下
[解决办法]
我认为不会,虽然析构函数没有被声明称虚拟函数,只能说明通过基类指针删除派生类对象时调用基类的析构函数,但仍然是归还整个派生类对象。当然,这里面有个前提,是派生类中没有在堆中再分配的内存,并且需要在派生类的析构函数中释放。例如下面的应该就不行了:

class C:public B
{
  char * p;
public:
  C(){p=new char[128];}
  ~C(){delete [] p;}
};

这样一定会有内存泄露。

有一个原则,如果类是允许被继承的,那么,就应该将析构函数声明称虚拟的。或者说,希望通过基类指针删除派生类对象,就应该把析构函数声明称虚拟的。
[解决办法]
不会。

首先,delete的参数是void *,与类型无关;
其次,delete成功与否的关键在于,其传入的指针与new所得的指针是否一致;
而此处,B与A是单向集成关系,因此pa与new B并无偏移,因此此处的delete是能成功的。

另可实践以下例子:C继承自A与B,A与B无关联,析构函数非虚,那么A *pa = new C, delete A与B *pb = new C, delete B有无不同。
[解决办法]
绝对不会,
new = malloc(分配sizeof(B)的空间) + 调用构造函数
你delete传的还是同一个指针的地址,当然会释放掉全部内存


delete = 调用析构函数(至于调用的是谁那是语法的事) + free(分配的sizeof(B)空间)

不要被C++的什么继承迷惑了,在底层只有指针和数据。

[解决办法]
不会泄露, 看了楼主的故事! 感觉那个面试官吧, 很二

但是楼主没必要发那么大火

这个东西么 平时大家加上个virtual就可以了 免得跟他废话
[解决办法]
这个问题越来越有趣了。

A所说“有的编译器会,有的不会”又引起了我更多的思考,其实问题就在于这个未定义行为是否包括解除分配函数没有被调用或者失败、失效,标准的相关内容:

5.3.5 Delete

1 The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.
   delete-expression:
        ::opt delete cast-expression
        ::opt delete [ ] cast-expression

.....
3 In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.73)


但是,标准也规定了一条确定的条款:

......
7 The delete-expression will call a deallocation function (3.7.3.2).

就是说,无论是否发生未定义行为,解除分配函数是一定会调用的,而只要满足传入的指针值(delete只关心指针值)是相应new返回的指针值,调用解除分配函数是一定会导致new所分配的n个字节的内存被释放的,除非指针值是非法的。

标准的内容:

3.7.3.2 Deallocation functions

.........
3 The value of the first argument supplied to one of the deallocation functions provided in the standard library may be a null pointer value; if so, the call to the deallocation function has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(size_t) or operator new(size_t, const std::nothrow_t&) in the standard library, and the value supplied to operator


delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](size_t) or operator new[](size_t, const std::nothrow_t&)in the standard library.

4 If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid
pointer value (including passing it to a deallocation function) is undefined.33)


因此我仍然倾向于不会发生内存泄漏,但尚未100%确定,因为上述依据是否足够尚存一点点疑虑。
[解决办法]
不会有泄漏,因为析构函数是trival的

热点排行