ここにディレクトリタイトルを書く
メモリ関連のバグ
1.よくある間違いのリファレンス
1.古典的なscanfバグ
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はinta[]を指します
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
正しい解決策1:ポインターのポインターを使用する
#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!
正しい解決策2: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!
3.解放されたときのポインタはNULLではありません
ワイルドポインタ:ポインタが指すコンテンツが無効であり、ポインタがNULLではありません
エラーの例:
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
2.メモリカバレッジ
一般的なもの
#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
一般的な2つ
#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);
一般的な3つ
char s[8];
int i;
gets(s); //假设用户输入了123456789
最大文字サイズのチェックなし
共通の4つ
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);
一般的な5
void dec_positive(int *a){
*a--;//先执行a--,从右往左结合
if(*a<0) *a=0; //此时指针a已经减一了
}
正しい書き込み:
(*a)--;
この書き込みは、aが指す変数の値を1つずつデクリメントします。
第三に、第二のリリース
エラーの例:
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已经释放了
}
5.メモリリーク
malloc、calloc、およびreallocによって取得されたメモリは、使用後に解放されません。メモリリークが発生します。
1.無料で使用するのを忘れる
foo(){
int *x=mallloc(N*sizeof(int));
...
return;//忘记使用free
}
2、無料は実行されない可能性があります
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并没有释放;
}