IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言中常见的内存相关的Bugs -> 正文阅读

[C++知识库]C语言中常见的内存相关的Bugs

常见的错误参考

经典的scanf bug

scanf需要传入的的变量对应的地址

#include<stdio.h>
int main(void){
   int i;
   double j;
   //wrong!!!错误的写法
   scanf("%d,%ld",i,j);
   //下面是正确的写法
   scanf("%d,%ld",&i,&j);
   
}

指针未正确初始化

当不知道指针正确的初始值时最好赋值为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初始化为100
    p=(char*)malloc(sizeof(char)*num); //随着栈的创建和销毁,变量p也随之消失
}                                       //整个过程只对p进行操作,并没有对str进行操作

int main(void){
    char *str=NULL;
    printf("%d\n",str);//0
    GetMemory(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);//0
    GetMemory(&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初始化为100
    char *p=(char*)malloc(sizeof(char)*num); //定义一个局部指针变量p,并对p赋值
    return p;                          //将这个值返回
}                                       

int main(void){
    char *str=NULL;
    printf("%d\n",str);//0
    str=GetMemory(100);//给str赋值为函数的返回值
    printf("%d\n",str);//
    strcpy(str,"hello world!");
    puts(str);
    free(str);
}

运行结果:

0
7161472
hello world!

指针被释放时没有置空

野指针:指针指向的内容已经无效了,而指针并没有被置空
错误示例:

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;
}

不要用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获取的内存,在使用完后,未释放。会造成内存泄漏。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-22 12:09:27  更:2021-11-22 12:10:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:36:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码