前言
-
- 常見錯誤
在實際項目中,經常會需要用到malloc申請動态記憶體,但使用不當經常會出現記憶體洩漏問題,下面給出了幾種常見的使用錯誤,以及較為正确的使用方法。
常見錯誤
- 使用局部指針變量申請動态記憶體
#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");//一般判斷不為空後,認為該指針是合法指針,進行其他操作
}
}
程式結果如圖所示:
可以看到,指針指向内容改變,但位址依然指向原來的位址,在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");//一般判斷不為空後,認為該指針是合法指針,進行其他操作
}
}
結果如圖所示: