C语言中常见的内存相关的Bugs
这里写目录标题
- 内存相关的Bugs
- 一、常见的错误参考
- 1、经典的scanf bug
- 2、指针未正确初始化
- 3、指针被释放时没有置空
- 4、不要用return语句返回指向“栈内存”的指针
- 二、内存覆盖
- 常见一
- 常见二
- 常见三
- 常见四
- 常见五
- 三、二次释放
- 四、引用已经释放的内存
- 五、内存泄漏
- 1、忘记用free
- 2、free可能执行不了
- 3、忘记释放结构体中malloc的指针
内存相关的Bugs
一、常见的错误参考
1、经典的scanf bug
scanf
需要传入的的变量对应的地址
#include<stdio.h>
int main(void){int i;double j;//wrong!!!错误的写法scanf("%d,%ld",i,j);//下面是正确的写法scanf("%d,%ld",&i,&j);}
2、指针未正确初始化
当不知道指针正确的初始值时最好赋值为NULL
错误示例:
//计算数组a的和
int sum(int a[],int n){int *p;int sum=0;for(int i=0;i<n;i++){sum+=*p++; //指针p并未初始化}
}
正确写法:*p 指向 int a[]
int sum(int a[],int n){int *p;p=a;int sum=0;for(int i=0;i<n;i++){sum+=*p++;}
}
经典错误示例:
#include<stdio.h>
#include<stdlib.h>
void GetMemory(char *p,int num){ //p初始化为NULL,num初始化为100p=(char*)malloc(sizeof(char)*num); //随着栈的创建和销毁,变量p也随之消失
} //整个过程只对p进行操作,并没有对str进行操作int main(void){char *str=NULL;printf("%d\n",str);//0GetMemory(str,100);//这里只是把str的值NULL传过去了printf("%d\n",str);//0 说明str的值并没有改变
}
运行结果
0
0
正确解法一:使用指针的指针
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void GetMemory(char **p,int num){ //p初始化为str的地址,num初始化为100*p=(char*)malloc(sizeof(char)*num); //所以*p相当于是地址为str的变量,也就是str,对str进行赋值
} //结束时p销毁,str的值已经改变int main(void){char *str=NULL;printf("%d\n",str);//0GetMemory(&str,100);//这里将str的地址传过去了printf("%d\n",str);//6833792 说明str的值改变strcpy(str,"hello world!");puts(str);free(str);
}
运行结果
0
6833792
hello world!
正确解法二:使用retrun返回值
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* GetMemory(int num){ //num初始化为100char *p=(char*)malloc(sizeof(char)*num); //定义一个局部指针变量p,并对p赋值return p; //将这个值返回
} int main(void){char *str=NULL;printf("%d\n",str);//0str=GetMemory(100);//给str赋值为函数的返回值printf("%d\n",str);//strcpy(str,"hello world!");puts(str);free(str);
}
运行结果:
0
7161472
hello world!
3、指针被释放时没有置空
野指针:指针指向的内容已经无效了,而指针并没有被置空
错误示例:
void relese_foo(int *p){ //定义了一个指针p,并将p的值初始化为pointer的值free(p);//释放这块内存p=NULL;//将p重新赋值为空,注意pointer的值并没有发生改变
}
int *pointer=(int *)malloc(sizeof(int));
int bar(){relese_foo(pointer);//将pointer的值传入return 0;
}
正确写法:
void relese_foo(int *p){free(p);
}
int *pointer=(int *)malloc(sizeof(int));
int bar(){relese_foo(pointer);pointer=NULL; //应该在此处置空return 0;
}
4、不要用return语句返回指向“栈内存”的指针
栈内的变量会随着函数的返回而销毁
倘若返回栈内存的指针,这个指针也是个野指针
错误示例:
#include<stdio.h>
#include<string.h>
char *getString(void){char p[]="hello world";return p; //返回的这个地址内的内容已经无效了
}
int main(void){char *str=NULL;str=getString();puts(str);//str的内容是垃圾
}
运行结果:编译器会报警告
ptr.c: In function 'getString':
ptr.c:6:5: warning: function returns address of local variable [enabled by default]
��a
二、内存覆盖
常见一
#define array_size 100
int *a=(int *)malloc(sizeof(int)*array_size);
for(int i=0;i<=array_size;i++){a[i]=NULL;
}
正确写法:将
i<=array_size
改为i<array_size
常见二
#define array_size 100
int *a=(int *)malloc(array_size);
for(int i=0;i<array_size;i++){a[i]=NULL;
}
正确写法:
int *a=(int *)malloc(sizeof(int)*array_size);
常见三
char s[8];
int i;
gets(s); //假设用户输入了123456789
没有检查最大字符的大小
常见四
char* heapify_string(char* s){int len=strlen(s);char *new_s=(char *)malloc(len);strcpy(new_s,s);return new_s;
}
字符串必须以0x00结束
正确写法:char *new_s=(char *)malloc(len+1);
常见五
void dec_positive(int *a){*a--;//先执行a--,从右往左结合if(*a<0) *a=0; //此时指针a已经减一了
}
正确写法:
(*a)--;
这种写法会将a指向的变量的值减一
三、二次释放
错误示例:
void my_write(int *x){...use x...free(x);
}
int *x=(int *)malloc(sizeof(int)*N);
my_read(x);
my_write(x);
free(x);//二次释放
四、引用已经释放的内存
错误示例:
x=malloc(N*sizeof(int));
free(x);
...
y=malloc(M*sizeof(int));
for(int i;i<M;i++){y[i]=x[i]++;//x已经释放了
}
五、内存泄漏
malloc、calloc、realloc获取的内存,在使用完后,未释放。会造成内存泄漏。
1、忘记用free
foo(){int *x=mallloc(N*sizeof(int));...return;//忘记使用free}
2、free可能执行不了
void my_function(char* msg){char *full_msg=(char *)malloc(strlen(msg)+100);strcpy(full_msg,"error was encountered");strcat(full_msg,msg);if(!display(full_msg)){return;//应该在这句之前加上free(full_msg);}free(full_msg);//如果上面的return执行了,那么内存不会释放;}
3、忘记释放结构体中malloc的指针
typedef struct
{char *name;int age;char *address;int phone;
}Person;
void my_function(){Person *p=(Person*)malloc(sizeof(Person));p->name=(char *)malloc(M);... p->address=(char *)malloc(N);...//正确写法:应该先释放结构体内的指针// free(p->name);// free(p->address;)free(p);//只释放了P,结构体内的name和address并没有释放;
}
C语言中常见的内存相关的Bugs相关推荐
- Go语言中常见的并发模式
Go语言最吸引人的地方是它内建的并发支持.Go语言并发体系的理论是C.A.R Hoare在1978年提出的通信顺序进程(Communicating Sequential Process,CSP).CS ...
- C程序中常见的内存操作错误
对C/C++程序员来说,管理和使用虚拟存储器可能是个困难的, 容易出错的任务.与存储器有关的错误属于那些令人惊恐的错误, 因为它们在时间和空间上, 经常是在距错误源一段距离之后才表现出来. 将错误的数 ...
- 错误内存【读书笔记】C程序中常见的内存操作有关的典型编程错误
题记:写这篇博客要主是加深自己对错误内存的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 对C/C++程序员来讲,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的 ...
- c语言常见错误分析和程序调试,C语言中常见错误分析及程序调试
总结分析了C语言中常见错误及程序调试的相关技巧,以提高初学者的编程能力. 2 8 2月 0年l 0 电脑学习 第6 期 C语言中常见错误分析及程序调试 陈伟' 陈东淼 摘要:总结分析了 C语言中常见错 ...
- c语言初学者常见错误归纳,C语言中常见错误分析.doc
C语言中常见错误分析 摘要:C语言是许多高校开设的第一门程序设计语言,使用方便灵活.根据C语言的特点,并结合实际教学,对在编程中经常遇到的错误进行分析.总结,为初学者尽快掌握C语言,提高程序设计水平提 ...
- C语言中的动态内存分配
大家好,今天简单讲一讲C语言中的动态内存分配. 补充:C程序中的内存块. 在C程序中,通常将内存划分为以下六个区域: (1)内核区域.这块区域是操作系统的,用户不能使用. (2)栈区.主要用于存放运行 ...
- Android开发中常见的内存泄露案例以及解决方法总结
Android开发中常见的内存泄露案例以及解决方法总结 参考文章: (1)Android开发中常见的内存泄露案例以及解决方法总结 (2)https://www.cnblogs.com/shen-hua ...
- Android中常见的内存泄露
内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏.内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会 ...
- C语言中常见的符号和注释的用法
文章目录 前言 一.换行符号\n \n的具体用法和作用 二.取地址符号& &的具体用法和作用 三.注释 注释的格式 注释的作用 注释在代码中的具体体现 总结 前言 本篇文章主要给大家讲 ...
最新文章
- Microbiome:重新定义“卫生”的概念
- python中平均值函数_python自定义函数ma(x,y)求简单平均值输出结果到列表
- Kdevelop的安装-2种方法
- LED驱动设计及实现
- windows安装pygame
- 消息中间件:为什么我们选择 RocketMQ
- 深度学习-Tensorflow2.2-批标准化简介-14
- 210129阶段三调试、进程间通信-共享内存
- 工作262:HBuilderX常见快捷键
- 页面增加html,为静态页面HTML增加session功能
- was supplied but isn‘t a known config
- 深度学习入门:基于Python的理论与实现——第一章Python入门
- 谷歌联网断网都可以玩的恐龙小游戏(内容有不死加速挂)
- python安装目录插件
- 微机原理与系统设计三:微处理器的结构与功能
- python matplotlib searbon 设置画版颜色 热力图固定颜色等级 固定比例尺寸大小
- 有关swin transformer相对位置编码的理解:
- 江苏省计算机一级考试题型分数,全国计算机一级考试时间、题型、分值
- 从51信用卡到OAuth2协议
- 边缘计算设备,手机循环经济的新出路
热门文章
- Android Camera 运行流程
- SpringBoot之maven包管理
- 图像处理自学(五):CAMERA驱动软件硬件架构V4L2
- java中panel显示不出来_为什么我的JPanel中的某些项目没有显示?
- Tcl Tutorial 笔记 ·ubuntu命令行运行tcl 命令
- 博图能打开s7200吗_透明胶真的能把车窗打开吗?现场实验给你看,能成功吗?...
- python爬虫定时爬取_如何用框架给python爬虫定时?
- 谷歌为什登不上去github_同声传译被攻陷!谷歌发布Translatotron直接语音翻译系统...
- 广西电力职业技术学院计算机应用,广西电力职业技术学院电子与信息工程系
- 现浇板用弹性计算方法_自建房砖混结构现浇楼板配筋的要求和计算方法