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

delete void指针解决方法

2012-04-03 
delete void指针孙鑫的深入详解上又一个错误,我已经发现书上的瑕疵不只一处了如下:structPRECVPARAM{SOCKE

delete void指针
孙鑫的深入详解上又一个错误,我已经发现书上的瑕疵不只一处了
如下:
struct   PRECVPARAM
{
          SOCKET   sock;
          HWND   hwnd;
};

CChatDialog::OnInitDialog(...)
{
          PRECVPARAM   *p=[b]new   PRECVPARAM[/b];
          p-> sock=m_socket;
          p-> hwnd=m_hWnd;
          HANDLe   hThread=CreateThread(NULL,0,RecvProc,(LPVOID)p,0,NULL)
          ...................
}

DWORD   WINAPI   RecvProc(LPVOID   lpParameter)
{
          SOCKET   sock=((PRECVPARAM   *)lpParameter)-> sock;
          HWND   hwnd=((PRECVPARAM   *)lpParameter)-> hwnd;
          [color=#FF0000][b]delete   lpParameter;[/b][/color]
          ...................
}

delete   lpParameter错了吧,
这是空指针,根本释放不了。

应该
delete   (PRECVPARAM   *)lpParameter;

各位认为如何呢???


[解决办法]
因为不同的指针寻址长度不同,delete时需要覆盖内存,如果长度出错可能在覆盖内存时越界;

据个例子

char *p = new char[1];
int *q=(int*)p;
delete p;

绝对错
[解决办法]
delete一个指针,和这个指针的类型无关,只要他是从new得到的就可以释放。
[解决办法]

探讨
引用:
引用:
这是空指针,根本释放不了。


谁说的空指针根本释放不了?


#include "iostream.h"

Class A
{
public:
    A(){}
    ~A(){cout < <"destroy A" < <endl;}
private:
    int x;
};

int main()
{
    A *pa=new A;
    void *p=(void *)pa;
    delete p;
    return 0;
}

怎么不调用析构函数呢??

[解决办法]
探讨
delete一个指针,和这个指针的类型无关,只要他是从new得到的就可以释放。

[解决办法]
探讨
因为不同的指针寻址长度不同,delete时需要覆盖内存,如果长度出错可能在覆盖内存时越界;

据个例子

char *p = new char[1];
int *q=(int*)p;
delete p;

绝对错

[解决办法]
探讨
引用:
引用:
引用:
引用:
这是空指针,根本释放不了。


谁说的空指针根本释放不了?


#include "iostream.h"

Class A
{
public:
    A(){}
    ~A(){cout < <"destroy A" < <endl;}
private:
    int x;
};

int main()
{
    A *pa=new A;
    void *p=(void *)pa;
    delete p;
    return 0;
}

怎么不调用析构函数呢??

你释放的是void类型不是class类型,当然不调用析构


回到主题。
我帖子中说的对吧
delete lpParameter;
改为
delete (PRECVPARAM *)lpParameter;


[解决办法]
探讨
楼上是什么意思,
你2星级上将,说说

[解决办法]
探讨
引用:


楼上是什么意思,
你2星级上将,说说

早就质疑孙鑫了;
这个家伙纯粹写书赚钱;VC,JAVA据说都有涉及,


[解决办法]
探讨
引用:
delete一个指针,和这个指针的类型无关,只要他是从new得到的就可以释放。


比较赞同这个看法,只要是new出来的,就delete,只要是new[]出来的,就delete[]
是不是这个类型,没关系,只要不是必须调用某个类的析构函数

[解决办法]
C/C++ code
delete void指针不行的吧,我觉得应该要知道该指针的类型的,void指针只存储了指向内存单元的首地址,但没有写明所指向的内存单元的长度啊
[解决办法]
探讨
看书得看前后文,我想这就是所谓断章取义

[解决办法]

void *一般称做范指针吧?! 指向一个用户类的对象没有任何问题呀。从 void *不能判定一定指向内置类型呀。


LZ 这个问题可以这样考虑。

delete 分2个子步骤。
1. 调用析构器
2. 释放本对象占有的堆上内存

由于采用了void *,导致编译器没有足够的信息合成调用析构器的代码。因此,析构器无法被调用了。可以确定的是本对象是被释放了。然而,需要在析构函数中做的事情都没有发生。

对于内置类型,无所谓,因为它们有一个可以忽略的析构器。
对于用户类型,要看是否有一个有意义的析构器。假设有,比如需要进一步释放在构造器内分配的内存,由于没有调用析构器,则发生内存泄露。再假设,需要在析构器中关闭数据库连接,那抱歉,数据库保持连接。

对于delete [] 可以有类似的分析。

LZ 进行类型转换的想法,是对的。
[解决办法]
探讨
引用:
 引用:
引用:
   引用:
  关于delete一个0指针,gcc的源码中有一段很有意思的注释。

  C/C++ codeif (p==0)return;/* Required by ANSI.  It's not my fault ...*/

     可以看到,delete一个0值指针没有任何问题。
     (其实到不了那一步,编译器一看是0指针,跳过析构函数和空间回收了)


[解决办法]
C/C++ code
//工程一下得到的结果:MyClass* p1  = new MyClass();p1->m_memory = new char[4];void*    p2;p2 = p1;delete p2;        // 报告内存泄露,大小为 4 bytep2 = new char[4];delete p2;        // 没有任何问题p2 = NULL;delete p2;        // 没有任何问题
[解决办法]
C/C++ code
#include <iostream>class A{public:    A()    {        std::cout << "A()" << std::endl;    }    ~A()    {        std::cout << "~A()" << std::endl;    }};int main(){    A* a = new A;    delete a;    //释放将会调用析构函数,因为知道他具有类类型    void *b = new A;    delete b;    //释放将不会调用析构函数         //我想这是他们的唯一区别吧,内存都可以得到释放,只是类型检查问题    system("pause");    return 0;}
[解决办法]
指针本身是能释放的。只是不能调用析构函数。也就说如果此对象里如果还有其他new的对象需要释放的话,那么那个new的对象没有被释放,就内存泄漏了。
[解决办法]
探讨
引用:
引用:
引用:
  引用:
  引用:
    引用:
    关于delete一个0指针,gcc的源码中有一段很有意思的注释。

    C/C++ codeif (p==0)return;/* Required by ANSI.  It's not my fault ...*/

      可以看到,delete一个0值指针没有任何问题。
      (其实到不了那一步,编译器一看是0指针,跳过析构函数和空间回收了)


我觉得你把红色字部分换成crt或者大部分编译器提供的delete的实现会让人更明白一些。
也许你可以说crt库是c++编译器的一部分,但是你肯定不能讲crt库就是编译器。我想在大部分情况下,编译器的事情大都在静态代码的生成上把。运行时指针的判断说是由编译器来做。。。


玩文字游戏有意思不?
词法分析,语法分析,语义分析,中间代码生成,中间代码优化,生成最终代码,连接器,装载器
是不是每次出现一个概念的时候,都要精确到其中某一个步骤?
或者对这个子步骤进一步划分, 直到小的不能再小?

热点排行