野指针的疑问


 // class that has a pointer member that behaves like a plain pointer
     class HasPtr {
     public:
         // copy of the values we're given
         HasPtr(int *p, int i): ptr(p), val(i) { }

         // const members to return the value of the indicated data member
         int *get_ptr() const { return ptr; }
         int get_int() const { return val; }

         // non const members to change the indicated data member
         void set_ptr(int *p) { ptr = p; }
         void set_int(int i) { val = i; }

         // return or change the value pointed to, so ok for const objects
         int get_ptr_val() const { return *ptr; }
         void set_ptr_val(int val) const { *ptr = val; }

     private:
         int *ptr;
         int val;
     };


我在VC下建立了一个工程,main函数运行下面这次代码,程序并没有当掉
     int *ip = new int(42); // dynamically allocated int initialized to 42
     HasPtr ptr(ip, 10);    // Has Ptr points to same object as ip does
     delete ip;             // object pointed to by ip is freed
     ptr.set_ptr_val(0); // disaster: The object to which Has Ptr points was freed!
对于野指针的操作,危害有哪些,哪些是会引起程序当掉

17 个解决方案

#1


你这么简单的程序看不出来,如果后面有new了新的对象,地址正好在你删掉的ip那里,那么你说ptr.set_ptr_val(0); 这句话是不是对你的新对象是破坏性的呢。

#2


你看这个代码就看出危害了


class Test
{
public :
Test(){}
virtual ~Test(){}
virtual void Func(){ cout<<"hello"<<endl;}
};


int main() 
{
  
int* p = new int[16];
delete p;
Test* t = new Test;
*p = 0; //这里野指针把t的虚表置成0了,所以下面这句会出错。
t->Func();

system("pause");   

}

#3


Mark

#4


野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
    “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:

一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例:

char *p = (char *) malloc(100);

strcpy(p, “hello”);

free(p);        // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL)   // 没有起到防错作用

   strcpy(p, “world”);  // 出错

另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释


转来的,可以看下

#5


引用 2 楼 xingzhe2001 的回复:
你看这个代码就看出危害了

C/C++ codeclass Test
{public :
    Test(){}virtual~Test(){}virtualvoid Func(){ cout<<"hello"<<endl;}
};int main() 
{int* p=newint[16];
    delete p;
    Test* t=new Test;*p=0;//这里野指针把t的虚表置成0了,所以下面这句会出错。    t->Func();
        
    system("pause");   

}

例子挺好的 学习了!

#6


什么是野指针?
  一个母亲有两个小孩(两个指针),一个在厨房,一个在卧室,(属于不同的代码块,其生存期不同)母亲让在厨房的小孩带一块蛋糕(指针指向的对象)给在卧室的小孩,这样在卧室的孩子才肯写作业。但这个在厨房的小孩比较淘气,他在走出厨房时自己将蛋糕吃了,没能带出来。而在卧室的没有吃到蛋糕,所以不肯完成他的作业。结果母亲却不知道卧室的孩子没有吃到蛋糕,还以为作业完了。结果第二天她就被老师召唤到办公室了。。。。。。。。事情麻烦了。
  这样,那个在卧室的孩子就是野指针了,因为他没有得到应得的蛋糕,不能完成母亲交给他的作业。
  这就是c中所讲的野指针。上面的小剧本不过演示了一种最基本的野指针的形成过程。更容易出现的情形是coder在编码时,大意之下使用了已经free过的指针。
  对于年轻点的经验欠缺的coder来说是比较容易犯的错误,经验老到的程序员或者慎重采取成对编程的形式避免这种失误,或者使用引用计数器防止形成野指针。
  总之,在c中,野指针也许性子野,但是控制起来也是有章可循。然而事情在c++中出现了变化。
  coder们面临更大的麻烦了。c++程序员无可避免的要写很多这样那样的类。谁让c++是面向对象的呢?
  我们在写类的时候难免要在构造函数中用new给类的指针数据成员分配内存。这本来没什么,动态分配内存是一种很常见的基本操作,我们在学数据结构时经常这么做,不是么?
  但是伙计,事情并非这么简单。类是一种高级的用户自定义数据类型,看起来和结构、枚举这样的用户自定义类型没啥太大差别。如果你这样认为。。。。那你会死的很惨。类太复杂了,普通情况下使用类的对象并没有太大的问题,但是,当你要复制一个对象时,问题就来了。
  比如我们知道,你要用一个对象初始化另一个对象时,c++是按位进行拷贝的(在某些情况下会使用默认生成的拷贝构造函数,而不是按位拷贝),即在内存里创建了初始化源对象的一个完全相同的拷贝。这在多数情况下已经足够了。但是,当你的对象在创建时为每个指针成员分配内存,也就是说类中有成员指向堆中的一块内存。当你的对象创建好后,类也将对象的指针成员指向了一块内存。如果你用这个对象去初始化另一个对象时,被初始化的对象和初始化的对象完全一样。这意味着,他们指向同一块内存,而不是重新为被初始化的对象分配内存。
  这样麻烦就大了。如果一个对象销毁了,那么分配的内存也就销毁了(别忘了,类是有析构函数的,它负责在对象销毁时,释放动态分配的内存。难道你说你不在类中写上析构部分?那么可怜的孩子,那你就走向了另一个深渊,当你的程序运行数小时之后,系统会告诉你,内存不够用了。。。想象一下把你的程序用在腾讯的服务器上。。。。。),另一个对象就残缺不全了,这就像一对连体婴儿,他们共用了一部分器官,心脏或者肝脏。要救活一个,就牺牲了另一个。一个得病了,另一个也要遭殃。
  可以说,这就是c++中更加变态的野指针。
  什么?你说我不用对象初始化对象?那么我们会不会将一个对象作为变元传递给函数呢?我们很多时候都这样做。有时我们不得不将对象按值传递给一个函数,但是你要知道,按值传递是什么意思?它的意思就是,把实参的一个拷贝交给函数使用。这和刚才的初始化没什么两样,多数情况是按位拷贝,函数体内的对象与外面的对象的指针将指向同一块内存,即便在函数中的对象没有对这块内存进行过操作,但是当函数结束时。。。。析构函数将会被调用。。。。。。。。
    还有一种与之相反的情况。。。 当你想要把一个在函数内的对象值返回给外面的对象时,这时候,函数内的对象会被析构。。。。同样一块内存被释放了两次。其后果是不可预见的。

    当你把一个对象的值赋给另一个对象时,如果你没有重载赋值运算符,那么也可能会导致按位拷贝(当调用编译器生成的构造函数时一样会出问题)。最终产生一个野指针(一个隐藏在类内的毒瘤),或者释放同一块内存多次。
    
    看到了么?害怕了么?是不是感到C++到处都是陷阱呢?不但有陷阱,到处都是危险品。所有c中的疑难问题,到了c++就成了一般问题了。好了不废话了,我们继续讲讲解决之道。

    对于最后的这种赋值的情况,我们只有通过重载赋值运算符才能解决,也就是避免按位拷贝。
    至于前面的都属于初始化,概括下来就是三种情况:
    1.当一个对象初始化另一个对象时,例如在声明中;
    2.把所创建的对象拷贝(按值)传递给一个函数时;
    3.生成临时对象时,最常见的就是函数的返回值。
    解决初始化时的按位拷贝问题(嗯嗯,可以明确地说,如果这个类的基因中没有任何虚的东西(虚基类,虚函数),它就会按位,但是不按位也会出同样的问题,所以对我们来说没什么区别),我们通过创建拷贝构造函数来解决。
  基本的拷贝构造函数形式为:
    classname (const classname &o)
          {
                //body here
          }
拷贝构造函数就是针对这个问题而设计的。

#7


mark

#8


同意4楼观点
对于野指针进行操作的主要危害就是你的程序能不能正常运行全看运气。
如果你释放的内存空间没有被覆盖,或者你的指针指向的内存空间中的
数据真好正确的,那么你的程序就可以正常执行。反之你的程序可能会
报错或出现错误的执行结果。

#9


引用 4 楼 fhtingtian 的回复:
野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
    “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:

一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例:

char *p = (char *) malloc(100);

strcpy(p, “hello”);

free(p);        // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL)  // 没有起到防错作用

  strcpy(p, “world”);  // 出错

另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释


转来的,可以看下


请问 strcpy(p, “world”);  为什么会出错呢

#10


  delete p 之后 指针p并不是NULL 原来的地址还存在

  所以有时比较if(NULL != p)  这里会出错

#11


引用 5 楼 beyond071 的回复:
引用 2 楼 xingzhe2001 的回复:
你看这个代码就看出危害了

C/C++ codeclass Test
{public :
    Test(){}virtual~Test(){}virtualvoid Func(){ cout < <"hello" < <endl;}
};int main()
{int* p=newint[16];
    delete p;
    Test* t=new Test;*p=0;//这里野指针把t的虚表置成0了,所以下面这句会出错。    t->Func();
       
    system("pause"); 

}

例子挺好的 学习了!

楼主以为只有crash才算出错,那么这个程序告诉楼主野指针可能导致crash

#12


野指针的危害是潜在的,可能不出错,可能每次都出错。如果运气很差,可能1000次才出一次错。

#13


delete ip;            // object pointed to by ip is freed 
    ptr.set_ptr_val(0); // disaster: The object to which Has Ptr points was freed! 

你的这个。。ptr对象的生命周期还没结束。。。它当然也有两个域啊。。。
一个是ptr指针域,一个是int,只是指针域所指向的内存被释放了。。。成为了野指针

然后这个时候你访问野指针指向的东西。。。而且恰好这个时候野指针指向的东西是可写的。所以没出错。。

其实这里野指针指向的内存是过期了的东西。。。因为它已被释放回收。。。已经不属于它自身了。所以说
是过期食品,而过期食品吃着不是总会出问题的,只是有时候会出问题而已。。。。

假使。。。野指针指向的内存又被分配给其他变量或者对象,如果分配的是可读的。。则一定会出错吧。。
或者。。。野指针修改了不属于它自身拥有的东西。如果它所修改的数据恰好是另外一个程序所用到得数据。。则很明显。。。另外一个程序就可能会挂掉。。。毕竟留下了安全隐患

#14


引用 4 楼 fhtingtian 的回复:
野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。
    “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:

一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。例:

char *p = (char *) malloc(100);

strcpy(p, “hello”);

free(p);        // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL)  // 没有起到防错作用

  strcpy(p, “world”);  // 出错

另外一个要注意的问题:不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释


转来的,可以看下

正解。
因为指向的东西未知。
所以危险。

#15


对于野指针的操作,危害有哪些,哪些是会引起程序当掉

楼主,有时间研究下内存管理,就知道野指针的危害了。

#16


野指针应该就是那些叫悬浮指针,迷途指针的吧,把它滞空应该可以再次用吧。不知对不。

#17


野指针,因为野,所以不确定,危害是不确定的,说不定什么时候就会出来咬你一口!

指针这东西,记住任何时候都要知道你的指针指向什么地方就OK了!
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告