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

Posted 王亦优 foxny

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了几道经典动态内存分配笔试题!楼下大爷做完直呼就这?(题目+答案+详解)C语言相关的知识,希望对你有一定的参考价值。

📌 本文作者: 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;
}


本章完

以上是关于几道经典动态内存分配笔试题!楼下大爷做完直呼就这?(题目+答案+详解)C语言的主要内容,如果未能解决你的问题,请参考以下文章

C语言之动态内存管理(动态内存分配+经典笔试题+柔性数组)[建议收藏]

动态内存管理详解(动态内存函数介绍 + 常见动态内存错误 + 经典笔试题)

C语言——动态内存管理经典笔试题+柔性数组

动态内存管理(动态内存函数的介绍,c/c++经典笔试题,柔性数组)

动态内存管理(动态内存函数的介绍,c/c++经典笔试题,柔性数组)

java并发面试题,看完直呼内行