📌 本文作者: Foxny
📃 更新記錄: 2021.8.8
? 勘誤記錄: 無
💬 參考資料: 高質量的C++/C編程指南、位元科技、Nice筆試題
📜 本文宣告: 由于作者水平有限,本文有錯誤和不準確之處在所難免,本人也很想知道這些錯誤,懇望讀者批評指正!

(共4道大題,每題25分,滿分100分)
📚 選自高質量的C++/C編程指南、Nice2016校招筆試題
🚪 傳送門:【維生素C語言】動態記憶體管理 (相關知識點復習)
第一題:
💬 下列代碼存在什么問題?請指出問題并做出相應的修改,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
💡 參考答案:str 傳給 GetMemory 函式時為值傳遞,所以 GetMemory 函式的形參 p 是 str 的一份臨時拷貝,在 GetMemory 函式內部動態開辟的記憶體空間的地址存放在了 p 中,并不會影響 str,所以當 GetMemory 函式回傳之后, str 仍然是 NULL,導致 strcpy 拷貝失敗,其次,隨著 GetMemory 函式的回傳,形參 p 隨即銷毀并且沒有及時的使用 free 釋放,從而導致動態開辟的100個位元組存在記憶體泄露問題,根據經驗,程式會出現卡死的問題,
🔑 詳細決議:

? 代碼修改:
① 回傳 p ,讓 str 接收:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ↓ 修改回傳型別為char*
char* GetMemory(char *p) {
p = (char*)malloc(100);
return p; // 將p帶回來
}
void Test() {
char *str = NULL;
str = GetMemory(str); // 用str接收,此時str指向剛才開辟的空間
strcpy(str, "hello world"); // 此時copy就沒有問題了
printf(str);
// 用完之后記得free,就可以解決記憶體泄露問題
free(str);
str = NULL; // 還要將str置為空指標
}
int main() {
Test();
return 0;
}
🚩 hello world
② 將值傳遞改為址傳遞:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ↓ 用char**接收
void GetMemory(char** p) {
*p = (char*)malloc(100);
}
void Test() {
char *str = NULL;
GetMemory(&str); // 址傳遞,就可以得到地址
strcpy(str, "hello world");
printf(str);
// 記得free,就可以解決記憶體泄露問題
free(str);
str = NULL; // 還要將str置為空指標
}
int main() {
Test();
return 0;
}
🚩 hello world
第二題:
💬 下列代碼存在什么問題?
#include <stdio.h>
#include <stdlib.h>
char* GetMemory(void) {
char p[] = "hello world";
return p;
}
void Test(void) {
char *str = NULL;
str = GetMemory();
printf(str);
}
int main() {
Test();
return 0;
}
💡 參考答案:GetMemory 函式內部創建的陣列實在堆疊區上創建的,出了函式 p 陣列的空間就還給了作業系統,回傳的地址是沒有實際意義的,如果通過回傳的地址去訪問記憶體,就會導致非法訪問記憶體問題,
🔑 詳細決議:

第三題:
💬 下列代碼存在什么問題?請指出問題并做出相應的修改,
#include <stdio.h>
#include <stdlib.h>
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;
}
💡 參考答案:沒有 free,導致記憶體泄露,
🔑 詳細決議:

? 代碼修改:
#include <stdio.h>
#include <stdlib.h>
void GetMemory(char **p, int num) {
*p = (char *)malloc(num);
}
void Test(void) {
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
// 釋放并置空
free(str);
str = NULL;
}
int main() {
Test();
return 0;
}
第四題:
💬 下列代碼存在什么問題?請指出問題并做出相應的修改,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
💡 本題答案:free 之后沒有將 str 置為空指標,導致 if 為真,對已經釋放掉的記憶體進行了訪問,引發非法訪問的問題,
🔑 詳細決議:

? 代碼修改:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Test(void) {
char *str = (char *) malloc(100);
strcpy(str, "hello");
free(str);
str = NULL; // 置空
if(str != NULL) {
strcpy(str, "world");
printf(str);
}
}
int main() {
Test();
return 0;
}
本章完
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292951.html
標籤:其他
下一篇:資料結構之佇列
