深⼊理解C 语⾔-指针使⽤的常见错误
在C 语⾔中,指针的重要性不⾔⽽喻,但在很多时候指针⼜被认为是⼀把双刃剑。下⾯总结⼀下指针使⽤的常见错误。
⼀⽅⾯,指针是构建数据结构和操作内存的精确⽽⾼效的⼯具。另⼀⽅⾯,它们⼜很容易误⽤,从⽽产⽣不可预知的软件bug 。⼀、使⽤未初始化的指针这个错误很常见,指针未初始化时,系统会给指针分配个随机地址,⽰例如下:
int *p; //或者 int *p = NULL;
···
c++strcpy函数用法*p = 10; //错误,指针未初始化上述程序将值10写到未知的内存位置,如果p 指向系统内存空间,这样很可能把系统本来地址⾥的内容给覆盖了,会导致程序或者系统的崩溃。
⼆、没有释放内存在堆中开辟内存以后,使⽤完成必须释放内存,否则会造成内存泄漏,⽰例如下:int *p = (int *)malloc(100);
···
free(p);
p = NULL;
三、不断修改内存指针变量
很多时候使⽤指针开辟了内存空间,然后如果对指针指向进⾏改变操作,操作完成后直接释放内存,会释放了不该释放的位置;另外程序丢失了对已开辟内存空间的控制,造成内存泄漏,⽰例如下:
//这种时候⼀般会定义两个指向同⼀个开辟的内存空间的指针变量,⼀个⽤于操作,⼀个⽤于释放,避免造成内存泄漏char *p = (char *)malloc(100);
strcpy(p, "abcdefg");
p += 1; //对指针指向进⾏改变操作
*p = 'a';
free(p);
p = NULL;
四、注意"野指针"
"野指针"不是NULL 指针,是指向“垃圾”内存的指针。⼈们⼀般不会错⽤NULL 指针,因为⽤if 语句很容易判断。但是“野指针”是很危险的,if 语句对它不起作⽤。“野指针”的成因主要有两种:
第⼀种,指针变量没有初始化。任何指针变量刚被创建时不会⾃动成为NULL 指针,它的缺省值是随机的,它会乱指⼀⽓。⽰例如下:char *p; //错误,未初始化,成为野指针
第⼆种,指针变量被free 或者delete 之后,没有置为NULL ,让⼈误以为是个合法的指针。⽰例如下:
char *p = (char *)malloc(100);
...
free(p); //错误,没有置为NULL ,成为野指针
五、指针参数申请内存的常见错误
如果函数的参数是⼀个指针,不要指望⽤该指针去申请动态内存,⽰例如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getMemory(char *p, int num)
{
p = (char*)malloc(sizeof(char) * num);
}
int main()
{
char *pStr = NULL; pStr = getMemory(pStr, 200);
strcpy(pStr, "hello world!"); //错误,pStr 仍然是空指针
printf("%s", pStr); free(pStr);
pStr = NULL;
return 0;
}
上⾯并没有使pStr 获得期望的内存,pStr 依旧是NULL ,为什么?
getMemory(str, 200)问题出在函数中。事实上,每执⾏⼀次函数就会泄漏⼀块内存,因为没有⽤free 释放内存。
getMemory 编译器总是要为函数的每个参数制作临时副本,指针参数p 的副本是_p ,编译器使_p = p 。在本例中,_p 申请了新的内存,只是把_p 所指的内存地址改变了,但是p 丝毫未变,仍然是空指针。getMemory 第⼀种⽤法:使⽤函数返回值来传递动态内存,⽰例如下:
指针参数申请内存的两种正确⽤法#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* getMemory(char *p, int num)
{
p = (char *)malloc(sizeof(char) * num);
return p;
}
int main()
{
char *pStr = NULL;
pStr = getMemory(pStr, 200); strcpy(pStr, "hello world!");
printf("%s", pStr);
free(pStr);
pStr = NULL;
return 0;
}
这⾥强调不要⽤return 语句返回指向”栈内存“的指针,因为”栈内存“指针在函数结束时已经被⾃动回收。
第⼆种⽤法:使⽤指向指针的指针作为参数来传递动态内存,⽰例如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getMemory(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num);
}
int main()
{
char *pStr = NULL;
getMemory(&pStr, 200);
strcpy(pStr, "hello world!");
printf("%s", pStr);
free(pStr);
pStr = NULL;
return 0;
}
在需要修改指针变量本⾝的时候,需要使⽤指向指针的指针作为参数,这也是传值与传地址的差别所在。参考:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论