几道经典动态内存分配笔试题!楼下大爷做完直呼就这?(题目+答案+详解)【C语言】

【维生素C语言】经典动态内存分配笔试题(题目+答案+详解)_#include

前言:

题目选自高质量的C++/C编程指南、Nice2016校招笔试题。

 (共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

🔑 详细解析:

【维生素C语言】经典动态内存分配笔试题(题目+答案+详解)_#include_02

⚡ 代码修改:

① 返回 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 数组的空间就还给了操作系统,返回的地址是没有实际意义的,如果通过返回的地址去访问内存,就会导致非法访问内存问题。

🔑 详细解析:

【维生素C语言】经典动态内存分配笔试题(题目+答案+详解)_笔试题_03


 第三题:

💬 下列代码存在什么问题?请指出问题并做出相应的修改。

#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,导致内存泄露。

🔑 详细解析:

【维生素C语言】经典动态内存分配笔试题(题目+答案+详解)_Test_04

⚡ 代码修改:

#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 为真,对已经释放掉的内存进行了访问,引发非法访问的问题。

🔑 详细解析:

【维生素C语言】经典动态内存分配笔试题(题目+答案+详解)_笔试题_05

⚡ 代码修改:

#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;
}

参考资料:

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

比特科技. C语言进阶[EB/OL]. 2021[2021.8.31]. .

林锐博士. 《高质量C/C++编程指南》[M]. 1.0. 电子工业, 2001.7.24.

nice公司. nice校招笔试题[EB/OL]. 2016[]. .

📌 本文作者: 王亦优

📃 更新记录: 2021.8.8

❌ 勘误记录: 无

💬 参考资料: 高质量的C++/C编程指南、比特科技、Nice笔试题

📜 本文声明: 由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

本章完。