常见的指针问题

本文探讨了C语言编程中常见的五种指针错误:使用未初始化的指针、使用含有非法值的指针、存储空间释放后继续使用、未释放已分配的存储空间以及不当的数据类型访问间接数据。每种错误都附有代码示例,帮助读者理解并避免这些陷阱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,所用的指针未初始化。

int main()

{

  static int *pointer;

 *pointer = 0;

}

尽管声明的是静态变量,从技术上讲已初始化为0,也就是NULL,但静态初始化并没有将指针初始化为有效的地址。因此,当程序运行时,变量pointer未包含有效的地址,程序就无法运行。下面为正确的程序:

int main()

{

 static int i;

 static int *pointer=&i;

*pointer = 0;

}

 

2, 所用的指针含有非法值

程序员使用指针的第二个毛病,就是给其赋了无效值。这里的“无效”意为并非内存中实际数据的地址。这可以看成是上个毛病的引申----倘若没有初始 化,内存中的垃圾位只会给出无效地址。其效果是一样的。如果试图解析包含无效地址的指针,要么得到内存访问冲突异常,要么访问的是不可预知的地址。因此, 解析指针变量时务必小心,确保对指针赋了有效地址值后使用之。

 

 

3,存储空间释放后仍试图继续使用之

第三个毛病就是所谓的指针悬空问题,看下面的例子:

int *p ;

p=malloc(sizeof(int));

*p=0;

free(p);

*p=5;

本例中,程序先分配了某个存储单元,并将其地址保存到变量p中。代码使用了此存储单元后将其释放掉,后者返回系统以供它用。注意,调用free并不 改变所分配内存的任何数据。它不改变p的值,p仍指向先前已malloc分配的存储单元。但是请注意,对free的调用告诉系统,程序已不再要此内存,系 统可将此内存区挪作它用。free函数并没有强制我们永远不再访问该内存的数据,我们仅仅承诺“不再用”而已。当然这段代码没有信守承诺。程序的最后一条 语句将5保存到p所指的内存单元。

指针悬空的最大麻烦是,有些时候我们还能用这些指针,所以不会立即意识到问题存在。只有系统没有将我们先前释放的存储空间用到别处,使用悬空的指针 还不会对程序有负面作用。然而随着malloc的每次调用,系统可能会重用一起free释放的内存单元。一旦重用这些单元,后续对悬空指针的解析就会导致 不可知的后果。问题可能包括从已被覆盖的单元读数据,覆盖掉新数据,更坏的情况是覆盖了系统的堆管理指针,这样导致程序崩溃!解决的办法很明确——既然释 放了指针所指的存储空间,就不要再用这个指针。

 

4,程序用过某存储空间后却不释放。

在所有这些毛病中,不释放指针所指的存储空间大概对程序的正常工作影响最小。下面的C语言代码展示出这类问题:

ptr = malloc(256);

   .

   .

ptr = malloc(512);

这个例子中,程序先分配256字节存储空间,以变量ptr指向之。后来,程序又分配了512字节存储空间,并改写变量ptr,使之指向新分配的内存 块。ptr先前保存的地址丢失。由于程序已经覆盖以前的ptr值,就无法将早先的256字节用free释放。于是,程序就无法再利用这256字节的存储空 间。

程序不能访问256字节的存储空间似乎没什么大不了的,但想想这段代码若在循环中执行,每次迭代都要丢失256字节。只要重复足够次数,程序就会耗光堆中的内存。这问题通常叫做“内存流失”,因为在程序执行过程中其效果如同内存不断从计算机流出一样。

比起指针悬空,内存流失还不算大问题。实际上,内存流失只有两个麻烦:

* 有耗光堆空间的危险,最终可能导致程序废止,不过这种现象很少见。

* 由于虚拟页交换而影响到程序的性能。

不管怎么样,应当养成分配存储空间后都要释放的习惯。

注意 :程序退出后,操作系统就能利用所有的内存空间,包括内存流失的那部分。所以内存流失只是对程序而言,不会对整个系统有内存损失。

 

5,使用不当的数据类型访问间接数据。

最后一个毛病是没有类型安全地访问指针,这样容易意外使用错误的数据类型。

char *pc;

 

pc=malloc(sizeof(char));

 

*((int*)pc)=5000;

一般来说,如果试图将值5000赋给pc所指的数据,编译器会满腹牢骚。因为5000无法放入char型的存储空间,后者只有1字节。然而本例通过“强制类型转换”告知编译器,pc为int型指针而非char型指针,编译器就认定这种赋值是合法的。

然而,倘若pc并未实际指向整数数据,则这段代码的最后一句可能引起灾难。字符是1字节,而整数要长一些。既然整数长于1字节,该赋值语句将会覆盖更多字节,而不光是malloc分配的那个字节。这是否会造成问题要看内存中紧邻该字符的数据是什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值