MST

星途 面试题库

面试题:C语言函数参数中数组名传递机制与内存管理深度探究

假设在一个复杂的C项目中,有一系列函数调用,其中一个函数 `void processArray(int arr[])` 接收一个数组参数。在函数内部,需要根据数组元素的某些条件动态分配内存并进行处理。由于C语言函数参数中数组名传递机制的特性,可能会导致内存管理上的隐患,请分析可能出现的内存问题(如内存泄漏、悬空指针等),并提出至少两种有效的解决方案,要求用代码示例及详细注释说明每种方案的原理和实现方式。
46.7万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

可能出现的内存问题分析

  1. 内存泄漏
    • 由于C语言函数参数中数组名会退化为指针,在processArray函数内部动态分配内存后,如果调用者没有正确处理这些内存,可能导致内存泄漏。例如,在processArray函数中分配了内存,但调用者不知道需要释放这些内存,就会造成内存泄漏。
  2. 悬空指针
    • 假设processArray函数分配了内存并返回一个指针给调用者,调用者释放了该内存,而processArray函数内部还保留着指向该内存的指针,就会产生悬空指针。当processArray函数再次使用这个指针时,就会导致未定义行为。

解决方案

  1. 方案一:让调用者负责内存分配和释放
    • 原理:调用者事先分配好所需内存,传递给processArray函数,函数在已有内存上进行操作,这样内存的分配和释放都由调用者控制,避免了内存泄漏和悬空指针问题。
    • 代码示例
#include <stdio.h>
#include <stdlib.h>

// 函数声明
void processArray(int arr[], int size);

int main() {
    int size = 5;
    // 调用者分配内存
    int *arr = (int *)malloc(size * sizeof(int));
    if (arr == NULL) {
        perror("malloc");
        return 1;
    }
    // 初始化数组
    for (int i = 0; i < size; i++) {
        arr[i] = i;
    }
    processArray(arr, size);
    // 调用者释放内存
    free(arr);
    return 0;
}

void processArray(int arr[], int size) {
    // 对数组进行处理,这里简单打印数组元素
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
  1. 方案二:使用结构体封装数组和内存管理函数
    • 原理:通过结构体将数组指针和相关的内存管理函数封装在一起,这样在processArray函数内部对内存的操作都在结构体的控制范围内,明确了内存的生命周期。
    • 代码示例
#include <stdio.h>
#include <stdlib.h>

// 定义结构体
typedef struct {
    int *arr;
    int size;
    void (*freeMemory)(struct ArrayWrapper *);
} ArrayWrapper;

// 释放内存的函数
void freeArray(ArrayWrapper *wrapper) {
    free(wrapper->arr);
    wrapper->arr = NULL;
    wrapper->size = 0;
}

// 处理数组的函数
void processArray(ArrayWrapper *wrapper) {
    // 对数组进行处理,这里简单打印数组元素
    for (int i = 0; i < wrapper->size; i++) {
        printf("%d ", wrapper->arr[i]);
    }
    printf("\n");
}

int main() {
    int size = 5;
    // 分配结构体内存
    ArrayWrapper *wrapper = (ArrayWrapper *)malloc(sizeof(ArrayWrapper));
    if (wrapper == NULL) {
        perror("malloc");
        return 1;
    }
    // 分配数组内存
    wrapper->arr = (int *)malloc(size * sizeof(int));
    if (wrapper->arr == NULL) {
        perror("malloc");
        free(wrapper);
        return 1;
    }
    wrapper->size = size;
    wrapper->freeMemory = freeArray;
    // 初始化数组
    for (int i = 0; i < size; i++) {
        wrapper->arr[i] = i;
    }
    processArray(wrapper);
    // 调用释放内存函数
    wrapper->freeMemory(wrapper);
    free(wrapper);
    return 0;
}