MST

星途 面试题库

面试题:C语言结构体指针的复杂内存管理与优化

假设有一个多层嵌套的结构体,如下: ```c struct Inner { char *str; int num; }; struct Outer { struct Inner *innerArr[5]; double value; }; ``` 编写代码实现:1. 正确分配内存并初始化这个多层嵌套结构体。2. 编写一个函数,将`Outer`结构体中所有`Inner`结构体的`num`值翻倍。3. 编写释放该结构体所有分配内存的函数,并确保没有内存泄漏。同时,分析并阐述在这种复杂结构体指针内存管理中可能遇到的常见问题及如何避免。
32.3万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 分配内存并初始化多层嵌套结构体
struct Outer* createOuter() {
    struct Outer* outer = (struct Outer*)malloc(sizeof(struct Outer));
    if (outer == NULL) {
        perror("malloc outer");
        return NULL;
    }
    outer->value = 0.0;

    for (int i = 0; i < 5; i++) {
        outer->innerArr[i] = (struct Inner*)malloc(sizeof(struct Inner));
        if (outer->innerArr[i] == NULL) {
            perror("malloc inner");
            // 释放已分配的内存
            for (int j = 0; j < i; j++) {
                free(outer->innerArr[j]);
            }
            free(outer);
            return NULL;
        }
        outer->innerArr[i]->str = (char*)malloc(10 * sizeof(char));
        if (outer->innerArr[i]->str == NULL) {
            perror("malloc inner str");
            // 释放已分配的内存
            for (int j = 0; j < i; j++) {
                free(outer->innerArr[j]->str);
                free(outer->innerArr[j]);
            }
            free(outer);
            return NULL;
        }
        strcpy(outer->innerArr[i]->str, "default");
        outer->innerArr[i]->num = 1;
    }
    return outer;
}

// 将Outer结构体中所有Inner结构体的num值翻倍
void doubleInnerNums(struct Outer* outer) {
    for (int i = 0; i < 5; i++) {
        outer->innerArr[i]->num *= 2;
    }
}

// 释放该结构体所有分配内存
void freeOuter(struct Outer* outer) {
    for (int i = 0; i < 5; i++) {
        free(outer->innerArr[i]->str);
        free(outer->innerArr[i]);
    }
    free(outer);
}

int main() {
    struct Outer* outer = createOuter();
    if (outer != NULL) {
        doubleInnerNums(outer);
        for (int i = 0; i < 5; i++) {
            printf("Inner %d: str = %s, num = %d\n", i, outer->innerArr[i]->str, outer->innerArr[i]->num);
        }
        freeOuter(outer);
    }
    return 0;
}

常见问题及避免方法

  1. 内存泄漏
    • 问题:在分配内存后,如果后续操作失败,没有释放已经分配的内存,就会导致内存泄漏。例如,在分配Inner结构体数组元素或str字符串内存失败时,没有释放之前已分配的Outer结构体或Inner结构体。
    • 避免方法:在每次分配内存后,立即检查返回值是否为NULL。如果分配失败,按照正确的顺序释放之前已经分配的所有内存。
  2. 悬空指针
    • 问题:当释放了一块内存,但没有将指向该内存的指针设置为NULL时,该指针就成为悬空指针。如果后续不小心使用了这个悬空指针,可能会导致程序崩溃。
    • 避免方法:在释放内存后,立即将指针设置为NULL。例如,在freeOuter函数中释放Outer结构体后,虽然这里没有后续使用指针的情况,但良好的习惯是将传入的指针参数设置为NULL
  3. 双重释放
    • 问题:对同一块内存进行多次释放会导致未定义行为。通常是由于逻辑错误,在代码的不同地方重复释放了同一块内存。
    • 避免方法:仔细设计内存管理逻辑,确保每块内存只被释放一次。可以通过设置标志位或者在释放内存后将指针置NULL,这样在尝试再次释放时可以通过判断指针是否为NULL来避免双重释放。