Erros comuns relacionados à memória na linguagem C

Erros relacionados à memória

1. Referência de erros comuns

1. Bug do scanf clássico

scanfO endereço correspondente à variável que precisa ser passada em

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

2. O ponteiro não foi inicializado corretamente

É melhor atribuir a NULL quando o valor inicial correto do ponteiro não for conhecido

Exemplo de erro:

//计算数组a的和
int sum(int a[],int n){
    
    
    int *p;
    int sum=0;
    for(int i=0;i<n;i++){
    
    
        sum+=*p++; //指针p并未初始化
    }
}

Ortografia correta: *p aponta para int a[]

int sum(int a[],int n){
    
    
    int *p;
    p=a;
    int sum=0;
    for(int i=0;i<n;i++){
    
    
        sum+=*p++;
    }
}

Exemplo de erro clássico:

#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的值并没有改变
}

resultado da operação

0
0

Solução correta 1: use o ponteiro do ponteiro

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

resultado da operação

0
6833792
hello world!

Solução correta 2: use reexecutar para retornar o valor

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

resultado da operação:

0
7161472
hello world!

3. O ponteiro não é NULL quando é liberado

Ponteiro curinga: o conteúdo apontado pelo ponteiro é inválido e o ponteiro não foi NULL

Exemplo de erro:

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

Pronúncia Correta:

void relese_foo(int *p){
    
    
    free(p);
}                                  
int *pointer=(int *)malloc(sizeof(int));
int bar(){
    
    
    relese_foo(pointer);
    pointer=NULL; //应该在此处置空
    return 0;
}

4. Não use a instrução return para retornar um ponteiro para "memória de pilha"

As variáveis ​​na pilha serão destruídas com o retorno da função.
Se o ponteiro para a memória da pilha for retornado, esse ponteiro também será um ponteiro curinga

Exemplo de erro:

#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的内容是垃圾
}

Resultado em execução: o compilador reportará um aviso

ptr.c: In function 'getString':
ptr.c:6:5: warning: function returns address of local variable [enabled by default]
��a

2. Cobertura de memória

comum

#define array_size 100
int *a=(int *)malloc(sizeof(int)*array_size);
for(int i=0;i<=array_size;i++){
    
    
    a[i]=NULL;
}

Ortografia correta: será i<=array_sizealterado parai<array_size

dois comuns

#define array_size 100
int *a=(int *)malloc(array_size);
for(int i=0;i<array_size;i++){
    
    
    a[i]=NULL;
}

Pronúncia Correta:int *a=(int *)malloc(sizeof(int)*array_size);

três comuns

char s[8];
int i;
gets(s); //假设用户输入了123456789

Sem verificação do tamanho máximo de caracteres

quatro comuns

char* heapify_string(char* s){
    
    
    int len=strlen(s);
    char *new_s=(char *)malloc(len);
    strcpy(new_s,s);
    return new_s;
}

A string deve terminar com 0x00
Ortografia correta:char *new_s=(char *)malloc(len+1);

cinco comuns

void dec_positive(int *a){
    
    
    *a--;//先执行a--,从右往左结合
    if(*a<0) *a=0; //此时指针a已经减一了
}

Escrita correta: (*a)--;
Esta escrita diminuirá o valor da variável apontada por um por um

Terceiro, o segundo lançamento

Exemplo de erro:

void my_write(int *x){
    
    
    ...use x...
    free(x);
}
int *x=(int *)malloc(sizeof(int)*N);
my_read(x);
my_write(x);
free(x);//二次释放

Quarto, consulte a memória que foi liberada

Exemplo de erro:

x=malloc(N*sizeof(int));
free(x);
...
y=malloc(M*sizeof(int));
for(int i;i<M;i++){
    
    
    y[i]=x[i]++;//x已经释放了
}

5. Vazamentos de memória

A memória adquirida por malloc, calloc e realloc não é liberada após o uso. causará um vazamento de memória.

1. Esqueça de usar gratuitamente

    foo(){
    
    
        int *x=mallloc(N*sizeof(int));
        ...
        return;//忘记使用free
    }

2, livre não pode ser executado

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. Esqueça de liberar o ponteiro malloc na estrutura

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并没有释放;
}

Acho que você gosta

Origin blog.csdn.net/weixin_47138646/article/details/121462234
Recomendado
Clasificación