MST
星途 面试题库

面试题:C语言动态内存管理及内存泄漏分析

假设你正在开发一个C语言程序,需要不断地动态分配和释放内存。请描述如何正确使用malloc、calloc、realloc和free函数来管理内存,避免内存泄漏。同时,如果程序出现了内存泄漏,你会采用哪些方法去定位和解决问题?
35.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 内存分配函数使用
    • malloc
      • malloc函数用于分配指定字节数的内存空间。其原型为void *malloc(size_t size)。例如,要分配一个大小为nint类型的数组空间,可以这样写:
int *arr = (int *)malloc(n * sizeof(int));
if (arr == NULL) {
    // 处理内存分配失败的情况,比如输出错误信息并退出程序
    perror("malloc");
    exit(EXIT_FAILURE);
}
  • calloc
    • calloc函数用于分配指定数量和指定大小的内存块,并将所分配的内存块初始化为零。其原型为void *calloc(size_t nmemb, size_t size)。例如,要分配nint类型的数组空间并初始化为0,可以这样写:
int *arr = (int *)calloc(n, sizeof(int));
if (arr == NULL) {
    perror("calloc");
    exit(EXIT_FAILURE);
}
  • realloc
    • realloc函数用于改变已分配内存块的大小。其原型为void *realloc(void *ptr, size_t size)。如果ptrNULLrealloc的行为就和malloc一样;如果size为0,并且ptr指向一个合法的内存块,realloc会释放该内存块并返回NULL。例如,假设已经有一个动态分配的数组arr,要扩展其大小:
int *new_arr = (int *)realloc(arr, new_n * sizeof(int));
if (new_arr == NULL) {
    // 处理内存重新分配失败的情况
    perror("realloc");
    // 可以考虑保留原有的arr数据,不进行释放,根据具体需求决定
    // free(arr);
    // arr = NULL;
} else {
    arr = new_arr;
}
  1. 内存释放函数free
    • 使用free函数来释放通过malloccallocrealloc分配的内存。例如:
free(arr);
arr = NULL; // 防止悬空指针
  1. 内存泄漏定位和解决方法
    • 工具辅助
      • Valgrind:在Linux系统下,可以使用Valgrind工具。例如,编译程序时确保使用-g选项保留调试信息(gcc -g -o program program.c),然后使用valgrind --leak-check=full./program运行程序。Valgrind会详细报告内存泄漏的位置,包括在哪个源文件、哪一行代码发生了内存泄漏。
      • AddressSanitizer:在GCC和Clang编译器中都支持AddressSanitizer。编译时添加-fsanitize=address选项(gcc -fsanitize=address -g -o program program.c),运行程序时,它会检测到内存泄漏并输出详细的错误信息,指出内存分配和未释放的位置。
    • 代码审查
      • 仔细检查代码中malloccallocreallocfree的配对使用。确保每个分配函数都有对应的free调用,并且free的调用时机正确。例如,在函数返回前,检查是否有未释放的动态分配内存。
    • 添加日志
      • 在内存分配和释放的地方添加日志输出。例如,使用printf函数记录每次malloccallocreallocfree的调用,包括分配的大小、地址等信息。这样在程序运行后,可以通过分析日志来查找可能的内存泄漏点。
#include <stdio.h>
#include <stdlib.h>

void *my_malloc(size_t size) {
    void *ptr = malloc(size);
    if (ptr) {
        printf("malloc: allocated %zu bytes at %p\n", size, ptr);
    } else {
        printf("malloc: allocation failed\n");
    }
    return ptr;
}

void my_free(void *ptr) {
    if (ptr) {
        printf("free: releasing memory at %p\n", ptr);
        free(ptr);
    }
}

int main() {
    int *arr = (int *)my_malloc(10 * sizeof(int));
    // 使用arr...
    my_free(arr);
    return 0;
}