一、例題
試問該段代碼能打印什么,或者不能打印什么,說出理由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib.h> 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 ; } |
這段代碼乍一看好像沒有啥問題,test函數(shù)進(jìn)去創(chuàng)建一個str嘛,然后str傳給getmemory函數(shù),開辟一塊空間,然后hello world這字符串放進(jìn)開辟的空間里,然后打印str也就是hello world嘛。
但是,上面的思路是完全錯誤的,代碼完全無法運行,解釋如下:
-
第一:你str傳到getmemory函數(shù)里,p開辟一個空間,被開辟的空間和str沒有關(guān)系
(傳值調(diào)用和傳址調(diào)用的區(qū)別) - 第二:你getmemory函數(shù)出來之后,開辟的空間沒有釋放掉,而且你p由于函數(shù)的結(jié)束已經(jīng)銷毀了,p銷毀之后再也無法找到開辟的空間,造成內(nèi)存泄漏
就比如p是一個警察頭子,開辟的空間是臥底,只有p知道那個臥底,你現(xiàn)在警察頭子死了,再也沒法證明臥底是臥底了
也就是說p消失后,沒辦法再對開辟的空間進(jìn)行釋放,這時就會造成內(nèi)存泄露
二、2種改進(jìn)方法
法1:二級指針(傳址調(diào)用)
代碼如下(示例):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void getmemory( char **p) { *p = ( char *) malloc (100); //p是str地址,*p是str } void test() { char *str = NULL; getmemory(&str); strcpy (str, "hello world" ); printf ( "%s" ,str); free (str); str = NULL; } int main() { test(); return 0; } |
因為之前的傳值調(diào)用沒法讓p和str建立聯(lián)系,那我們就傳地址,開辟一塊空間出來賦給*p
要注意的是,p是str地址嘛,*p也就是str,到這里,str掌握了新開辟空間的控制權(quán)。然后getmemory函數(shù)出來,進(jìn)行strcpy和printf操作,最后不要忘記free掉原先的空間。
法2:返回指針
代碼如下(示例):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
char * getmemory( char *p) { p = ( char *) malloc (100); return p; } void test() { char *str = NULL; str=getmemory(str); strcpy (str, "hello world" ); printf ( "%s" , str); free (str); str = NULL; } int main() { test(); return 0; } |
因為這里是開辟了一塊空間給指針p管理嘛,str和p沒有建立聯(lián)系,那你直接函數(shù)返回p這個指針然后賦值給str即可,隨后操作和方法1一樣
總結(jié)
本文介紹了動態(tài)內(nèi)存分配的常見例題及兩種改進(jìn)方法,讀者需要理解為何會發(fā)生內(nèi)存泄露和傳值與傳址調(diào)用的區(qū)別就可以熟練解決這類問題。以上,祝讀者學(xué)習(xí)愉快~希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/m0_57180439/article/details/120652651