C语言:动态内存错误

Posted 往明

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言:动态内存错误相关的知识,希望对你有一定的参考价值。

⭐️前言⭐️

经过前面动态内存相关知识的学习,我们本文就要来分析动态内存相关的问题。

🍃常见内存错误

🍂对NULL指针的解引用操作

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

🍂越界访问

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

🍂对非动态开辟内存使用free释放

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

🍂使用free释放一块动态开辟内存的一部分

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

🍂对同一块动态内存多次释放

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

🍂内存泄漏

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

🍃动态内存错误笔试题分析

🍂笔试题1

以下代码执行效果

void GetMemory(char* p){
	p = (char*)malloc(100);
}
void Test(){
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf("%s",str);
}
int main() {
	Test();
	return 0;
}

执行后:程序会崩溃

分析如下:
我们经过调试发现再执行GetMemory(str); 后str的地址还是等于NULL,那这是为什么呢?
那肯定是这个函数处理不当?
突然想起函数传递参数–传值调用,如下

void change(int a) {
	a = a + 1;
}
int main() {
	int a = 0;
	change(a);
	return 0;
}

在执行完后看似a的值加一,但是我们发现它还是0
对于这种情况也是一样,传值调用并不能改变值,要想达到目的需要进行传址调用。

void GetMemory(char** p){
	*p = (char*)malloc(100);
}
void Test(){
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
}
int main() {
	Test();
	return 0;
}

🍂笔试题2

char* GetMemory(void){
	char p[] = "hello world";
	return p;
}
void Test(void){
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
int main() {
	Test();
	return 0;
}

输出随机值

str接受了p的地址,但是在GetMemory函数结束后销毁,p函数中内存内容也被随机化,虽然拿到了地址,但是内容不再是hello world
这种情况对应野指针,指针指向的内容已被释放,对其解引用就会出错

int* change() {
	int n = 10;
	return &n;
}
int main() {
	int* p = change();
	printf(" \\n");
	printf("%d", *p);
	return 0;
}

输出的不是我们想要的10

🍂笔试题3

void GetMemory(char** p, int num){
	*p = (char*)malloc(num);
}
void Test(void){
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}
int main() {
	Test();
	return 0;
}

这道题就是笔试题1的正确写法,输出

hello

🍂笔试题4

void Test(void){
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL){
		strcpy(str, "world");
		printf(str);
	}
}
int main() {
	Test();
	return 0;
}

输出hello,word

分析:
         对于第一个输出hello很容易判断,在释放后str的内容虽然丢失了,但是str的地址还在,不为空,所以world被拷贝进去。

这也是前文介绍在释放后需要把指针指向NULL

⭐️结尾语⭐️

相关链接

⭐️上一篇:动态内存管理知识⭐️
⭐️下一篇:暂未更新⭐️
⭐️传值调用以及传值调用:函数⭐️

以上是关于C语言:动态内存错误的主要内容,如果未能解决你的问题,请参考以下文章

C语言动态内存分配

C语言----四道题充分体会动态内存错误

梦开始的地方—— C语言动态内存管理(malloc+calloc+realloc+free)

浅谈C语言的动态内存开辟

C语言进阶:动态内存管理

玩转C语言动态内存,轻松管理动态内存空间