面试可能遇到的问题野指针等解决方法

空指针:一般声明一个指针变量赋值为NULL,这就是空指针,各个类型的空指针都存在确确实实的内存地址,但是不会指向任何有效的值的内存地址,对空指针操作,例如访问属性和方法,会抛出空指针异常,因为空指针指向的内存地址没有对应的物理地址。

野指针:指那些释放内存,但是指针赋值为空,这时候的指针指向任意地址,例如指向内核地址或不属于本程序的内存地址,程序会被kill,即奔溃。

内存泄漏:分为堆泄露和资源泄露 两种,内存分配失败或者内存分配成功却没有指针指向它(即无法操作该内存),会导致内存分配的越来越多,导致系统内存不够而终止程序
(https://blog.csdn.net/jackshiny/article/details/43838919)

野指针出现情况(https://blog.csdn.net/qq_31930499/article/details/80166472):
(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。
解决方法,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存
(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指针。如果程序比较长,我们有时记不住p所指的内存是否已经被释放,在继续使用p之前,通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。
原文解释代码:

char *p = (char *) malloc(100);
strcpy(p, “hello”);
free(p);   // p 所指的内存被释放,但是p所指的地址仍然不变if(p != NULL)      // 没有起到防错作用
{
    strcpy(p, “world”);      // 出错
}

解决方法:指针指向的内存空间被释放后指针应该指向NULL。
3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:

class A 
{      
public:
     void Func(void){ cout << “Func of class A<< endl; }
};
void Test(void)
{
    A *p;
   {
      A a;
      p = &a; // 注意 a 的生命期 ,只在这个程序块中(花括号里面的两行),而不是整个test函数
   }
     p->Func();  // p是“野指针”
}

超出作用域
解决办法
在变量的作用域结束前释放掉变量的地址空间并且让指针指向NULL

(https://blog.csdn.net/qq_25073253/article/details/82918988)
C++没有垃圾回收机制,我们需要关注那些类型的内存泄漏?
堆内存泄漏。在内存中程序员手动分配的一块内存,malloc\realloc\new。完成相关操作后,没有调用相对应的free\delete释放掉内存,这时这块内存就会常驻内存,造成堆内存泄漏
系统资源泄漏。分配给程序使用的资源没有使用相应函数释放,如bitmap\handle\socket.
解决方法(https://zhuanlan.zhihu.com/p/110313333)
静态检测

所谓静态检测,就是不运行程序,在程序的编译阶段进行检测,主要原理就是对 new 与 delete, malloc 与 free 进行匹配检测,基本上能检测出 大部分 coding 中因为粗心导致的问题。

静态检测包括手动检测和静态工具分析,所谓手动检测嘛,就是叫大牛帮你review啦。下面介绍了常见的静态检测工具。常用的静态检测的工具有 splint, PC-LINT, BEAM 等,每种检测各有千秋,具体使用方法这里不在赘述,网上教程挺多的,也可以直接去看官方说明文档。但是静态检测不能判定跨线程的内存申请与释放。这时候就需要动态检测出场了。

动态检测

所谓动态检测,就是运行程序的过程中,对程序的内存分配情况进行记录并判定。常用的工具有 valgrind, Rational purify 等,没种工具有各自的特点,大家看情况自行选用。对于动态检测来说,最大的弊端就是会加重程序的负担,对于一些大型工程,涉及到多个动态库,带来的负担太重,这时候就需要自己根据需求写一套了。

你可能感兴趣的:(面试)