C言語による動的メモリ割り当て (3)

この章の焦点 (今日は一般的な動的メモリ エラーについて説明します)

一般的な動的メモリ エラーに直接ジャンプできます。動的メモリ割り当てとそれらの機能が存在する理由がまだ理解できない場合は、i の付いたリンクをクリックして確認してください。正式にトピックに入ります。

動的メモリ割り当てが存在する理由

以前にもお伝えしましたが以下のリンクを参照してください

動的メモリ関数の概要


動的メモリ割り当て (1)動的メモリ割り当て (2)についてはすでに説明しました。

マロック

以前にもお伝えしましたが上記のリンクを参照してください

無料

以前にもお伝えしましたが上記のリンクを参照してください

コールク

以前にもお伝えしましたが上記のリンクを参照してください

再ロック

以前にもお伝えしましたが上記のリンクを参照してください

一般的な動的メモリ エラー

1**** NULL ポインタの逆参照操作

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    
    
	int* p = (int*)malloc(40);
	//这种写代码的风格是由问题的,我们需要去判断p是否为空
	*p = 20;
	return 0;
}

その理由は、ここでは p が検出されないためです
。そのため、それを記述する正しい方法は何ですか。次のコードを参照してください。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    
    
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
    
    
		return 1;
	}
	*p = 20;
	return 0;
}

このコードは標準の動的メモリ開発コードです。

2. 動的に割り当てられたスペースへの境界外アクセス

//对动态开辟内存空间的越界访问
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<errno.h>
int main()
{
    
    
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
    
    
		printf("%s\n", strerror(errno));
		return 1;
	}
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
    
    
		p[i] = i;
	}
	free(p);
	p = NULL;
	return 0;
}

3. free を使用して非動的に割り当てられたメモリを解放します。

//对非动态开辟内存空间使用free释放
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    
    
	int a = 10;//这是栈上的内存空间,属于非内存动态内存开辟的空间使用free函数释放
	int* p = &a;
	free(p);//free释放的一定是malloc/calloc/realloc所动态开辟的内存空间
	p = NULL;
	return 0;
}

4. free を使用して、動的に割り当てられたメモリの一部を解放します。

//使用free释放一块动态开辟内存的一部分
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    
    
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
    
    
		return 1;

	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		*p = i;
		p++;
	}
	free(p);
	p = NULL;
	return 0;
}

ここでの p++ は最後に配列全体を生成しますが、最終的に p が指す空間を解放するときに、配列の空間 (または配列の一部のみ) を解放することができないため、このコードの書き方には問題があります。

5. 同じ動的メモリの複数のリリース

//对同一块动态内存多次释放
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    
    
	int* p = (int*)malloc(40);
	free(p);//一旦释放完p之后p就成为了野指针
	p = NULL;//这里我们一旦将p置为空指针(NULL),第二个free(p)就没用了,这时候我们将p置为空指针,这是他就不是野指针了
	free(p);//会报错,编译器会说我一级帮你释放一次了你还让我帮你释放一次//对同一块空间的两次释放
	return 0;
}

これが最初の空きです § スペースが解放されると、p はワイルド ポインタになります。これはワイルド ポインタ p です。1 つで十分であるのと同じように、ツリーに結び付ける必要があるため、NULL (空のポインタ) に設定します。 p がワイルド ポインタではない場合、2 番目の free§ は実行を継続しません。

6. メモリを動的に開いて解放し忘れる (メモリ リーク)

この知識点については動的メモリ割り当て (2)で説明しました。もう一度復習してください。

//动态开辟内存忘记释放(内存泄漏)
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
void test()
{
    
    
	int* p = (int*)malloc(100);
	int flag = 0;
	scanf_s("%d", &flag);
	if (flag == 5)
	{
    
    
		return;//...
		free(p);
		p = NULL;

	}
}


int main()
{
    
    
	test();
	//......
	return 0;
}

ここにフラグを入力してください。誰かが実際に 5 を入力して、よく考えて、ここで return を返し、main 関数に入ると、自由に実行する機会は決してなくなり、この動的に開かれたスペースは決して見つからず、誰も見つけることはできません。そのスペースを取得すると、メモリリークが発生します

//动态开辟内存忘记释放(内存泄漏)
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
int* test()
{
    
    
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
    
    
		return p;
	}
	//....
	return p;
}


int main()
{
    
    
	int* ret = test();
	//......
	return 0;
}

リリースを申請しましたが、リリースを忘れたので結果は間違っています

使用されなくなった動的に開かれた領域を解放し忘れると、メモリ リークが発生します。覚えておいてください
:
動的に開かれた領域は解放する必要があり、

上記のコードは私が書いたものです。今すぐコード テンプレートを提供します。3.1
NULL ポインタの逆参照操作する

void test()
{
    
    
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 free(p);
}

3.2 動的に割り当てられたスペースへの境界外アクセス

void test()
{
    
    
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
    
    
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
    
    
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
}

3.3 free を使用して非動的メモリを解放する

void test()
{
    
    
 int a = 10;
 int *p = &a;
 free(p);//ok?
}

3.4 free を使用して動的に割り当てられたメモリの一部を解放します

void test()
{
    
    
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向动态内存的起始位置
}

3.5 同じ動的メモリの複数のリリース

void test()
{
    
    
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重复释放
}

3.6 メモリを動的に開いて解放し忘れる (メモリ リーク)

void test()
{
    
    
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
    
    
 *p = 20;
 }
}
int main()
{
    
    
 test();
 while(1);
}

いくつかの古典的な筆記試験問題

次回のブログでご説明させていただきますので、お楽しみに

フレキシブルアレイ

以前にもお伝えしましたが、フレキシブル アレイ
を表示するには、下のリンクをクリックしてください。

おすすめ

転載: blog.csdn.net/fjj2397194209/article/details/131293778