天天看点

malloc动态内存如何正确使用

前言

    • 常见错误

在实际项目中,经常会需要用到malloc申请动态内存,但使用不当经常会出现内存泄漏问题,下面给出了几种常见的使用错误,以及较为正确的使用方法。

常见错误

  1. 使用局部指针变量申请动态内存
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void malloc_test(char* m, int num)
{
	m = (char *)malloc(sizeof(char) * num);
}

int main(int argc, char *argv[])
{
	char *str = NULL;//这边需要将初始化为NULL,防止成为野指针,发生未知错误
	malloc_test(str, 100);
	printf("malloc complete\n");
	strcpy(str, "test_str");//运行错误 
	printf("strcpy complete\n");//程序已崩溃,无法打印 
}
           

此段代码中,调用malloc_test函数时,使用局部指针变量char *m进行malloc申请动态内存,最终程序运行崩溃。为什么?

毛病出在malloc_test函数中,编译器会为函数的每一个参数创建一个副本,则m的副本为_m,当函数内运行malloc时,实际上是为_m申请了一片内存,而m实际上什么也没得到,指针依然为NULL,当运行到strcpy时,程序崩溃。

而这里还有一个错误,在malloc_test函数运行结束时,并没有去释放_m的内存,导致内存泄漏,且每运行一次,泄漏一次内存。

如果非要用参数的形式,进行动态内存申请,可以考虑二级指针的方式。如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void malloc_test(char** m, int num)
{
	*m = (char *)malloc(sizeof(char) * num);
}

int main(int argc, char *argv[])
{
	char *str = NULL;//这边需要将初始化为NULL,防止成为野指针,发生未知错误
	malloc_test(&str, 100);
	printf("malloc complete\n");
	strcpy(str, "test_str");//运行正常
	printf("strcpy complete\n");//打印正常 
}
           

当然,这种使用方式较为晦涩,最简单的是,我们可以用返回值的方式,完成动态内存申请。

#include <string.h>
#include <stdlib.h>

char* malloc_test(int num)
{
	char *opt = NULL;
	opt = (char *)malloc(sizeof(char) * num);
	return opt;
}

int main(int argc, char *argv[])
{
	char *str = NULL;//这边需要将初始化为NULL,防止成为野指针,发生未知错误
	str = malloc_test(100);
	printf("malloc complete\n");
	strcpy(str, "test_str");//运行正常
	printf("strcpy complete\n");//打印正常 
}
           

2.使用free后,并未把指针指向NULL。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	char *str = NULL;//这边需要将初始化为NULL,防止成为野指针,发生未知错误
	str = (char *)malloc(sizeof(char) * 100);
	strcpy(str, "hello world");
	printf("malloc complete str is :%s\n", str);
	printf("str address is %d\n", str);
	free(str);
	printf("after free str is :%s\n", str);
	printf("after free str address is %d\n", str);
	
	if(NULL != str)
	{
		printf("str is Not NULL");//一般判断不为空后,认为该指针是合法指针,进行其他操作 
	}
}
           

程序结果如图所示:

malloc动态内存如何正确使用

可以看到,指针指向内容改变,但地址依然指向原来的地址,在free指针时,被释放的只是str指向的那一篇内存,但是指针地址不变。当程序进行指针非空判断时,认为指针是合法指针,并进行内容改写等操作,将可能导致崩溃错误!

正确的做法应该是free完指针后,将指针置为NULL!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	char *str = NULL;//这边需要将初始化为NULL,防止成为野指针,发生未知错误
	str = (char *)malloc(sizeof(char) * 100);
	strcpy(str, "hello world");
	printf("malloc complete str is :%s\n", str);
	printf("str address is %d\n", str);
	free(str);
	str = NULL;
	printf("after free str is :%s\n", str);
	printf("after free str address is %d\n", str);
	
	if(NULL != str)
	{
		printf("str is Not NULL");//一般判断不为空后,认为该指针是合法指针,进行其他操作 
	}
}
           

结果如图所示:

malloc动态内存如何正确使用

继续阅读