MST

星途 面试题库

面试题:C语言结构体动态内存分配在多线程环境下的问题与解决方案

在多线程环境下,使用malloc为结构体动态分配内存可能会出现哪些问题?假设我们有一个结构体struct Shared { int value; char *text; }; 多个线程会同时对这个结构体进行动态内存分配、赋值和释放操作。请设计一个方案,确保内存操作的线程安全性,包括防止内存泄漏、避免竞态条件等问题。用代码示例结合文字描述说明实现过程和关键技术点。
44.3万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

多线程下使用 malloc 为结构体动态分配内存可能出现的问题

  1. 竞态条件:多个线程同时调用 malloc 为结构体分配内存,可能导致结构体的部分成员被不同线程同时修改,从而出现数据不一致的情况。例如,一个线程刚分配好内存并开始给 text 赋值,另一个线程可能同时在给 value 赋值,这可能导致赋值操作相互干扰。
  2. 内存泄漏:如果在释放内存时没有正确同步,一个线程可能在另一个线程仍在使用该内存时释放了它,导致悬空指针。另外,如果在分配内存失败时没有正确处理,也可能导致已分配的部分内存无法释放,造成内存泄漏。

确保内存操作线程安全性的方案

  1. 关键技术点

    • 使用互斥锁(mutex)来保护对结构体的所有操作,确保同一时间只有一个线程可以对结构体进行分配、赋值和释放操作。
    • 在分配内存时,要检查分配是否成功,避免因分配失败而导致内存泄漏。
    • 在释放内存时,要确保没有其他线程正在使用该内存,避免悬空指针。
  2. 代码示例(以 C 语言为例,使用 POSIX 线程库 pthread

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

// 定义共享结构体
struct Shared {
    int value;
    char *text;
};

// 定义互斥锁
pthread_mutex_t mutex;

// 线程函数,模拟对共享结构体的操作
void* thread_function(void* arg) {
    struct Shared *shared = (struct Shared *)arg;

    // 加锁
    pthread_mutex_lock(&mutex);

    // 分配内存
    shared->text = (char *)malloc(100);
    if (shared->text == NULL) {
        // 分配失败处理
        perror("malloc");
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
    }

    // 赋值
    shared->value = 42;
    snprintf(shared->text, 100, "Hello, from thread %ld", pthread_self());

    // 使用共享结构体数据
    printf("Thread %ld: value = %d, text = %s\n", pthread_self(), shared->value, shared->text);

    // 释放内存
    free(shared->text);
    shared->text = NULL;

    // 解锁
    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
}

int main() {
    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);

    struct Shared shared;

    // 创建多个线程
    pthread_t threads[3];
    for (int i = 0; i < 3; i++) {
        pthread_create(&threads[i], NULL, thread_function, &shared);
    }

    // 等待所有线程结束
    for (int i = 0; i < 3; i++) {
        pthread_join(threads[i], NULL);
    }

    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);

    return 0;
}

在上述代码中:

  • 定义了一个互斥锁 mutex,并在 main 函数中初始化它。
  • thread_function 函数中,每次对共享结构体 shared 进行操作前先加锁(pthread_mutex_lock),操作完成后解锁(pthread_mutex_unlock),这样就避免了竞态条件。
  • 在分配内存后检查是否成功,失败时进行相应处理并释放已分配的资源(如果有的话),防止内存泄漏。
  • 在释放内存后将指针置为 NULL,避免悬空指针。最后在 main 函数结束时销毁互斥锁。