天天看點

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動态記憶體如何正确使用

繼續閱讀