MST
星途 面试题库

面试题:C语言malloc分配结构体大内存后如何避免内存碎片化问题

假设我们有一个程序,会频繁地使用malloc为结构体分配大内存,同时也会频繁释放这些内存。随着程序运行,可能会出现内存碎片化问题,导致后续大内存分配失败。已知一个结构体定义如下: ```c #include <stdio.h> #include <stdlib.h> // 定义一个结构体 typedef struct { int value; char str[1000]; } MyStruct; ``` 请描述至少两种可以避免或缓解内存碎片化问题的方法,并给出相应的代码示例。
35.4万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

方法一:内存池技术

内存池是一种内存管理技术,它在程序启动时预先分配一大块内存,然后在需要时从这块内存中分配小块内存,使用完毕后再将小块内存归还到内存池,而不是直接调用 mallocfree 与操作系统交互。这样可以减少内存碎片的产生。

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

// 定义一个结构体
typedef struct {
    int value;
    char str[1000];
} MyStruct;

// 定义内存池相关结构体
typedef struct MemoryBlock {
    struct MemoryBlock* next;
} MemoryBlock;

typedef struct MemoryPool {
    MemoryBlock* freeList;
    size_t blockSize;
    size_t poolSize;
} MemoryPool;

// 创建内存池
MemoryPool* createMemoryPool(size_t blockSize, size_t numBlocks) {
    MemoryPool* pool = (MemoryPool*)malloc(sizeof(MemoryPool));
    if (pool == NULL) {
        return NULL;
    }
    pool->blockSize = blockSize;
    pool->poolSize = numBlocks;
    pool->freeList = (MemoryBlock*)malloc(blockSize * numBlocks);
    if (pool->freeList == NULL) {
        free(pool);
        return NULL;
    }
    MemoryBlock* current = pool->freeList;
    for (size_t i = 0; i < numBlocks - 1; ++i) {
        current->next = (MemoryBlock*)((char*)current + blockSize);
        current = current->next;
    }
    current->next = NULL;
    return pool;
}

// 从内存池分配内存
void* allocateFromPool(MemoryPool* pool) {
    if (pool == NULL || pool->freeList == NULL) {
        return NULL;
    }
    MemoryBlock* block = pool->freeList;
    pool->freeList = block->next;
    return block;
}

// 释放内存到内存池
void freeToPool(MemoryPool* pool, void* block) {
    if (pool == NULL || block == NULL) {
        return;
    }
    ((MemoryBlock*)block)->next = pool->freeList;
    pool->freeList = (MemoryBlock*)block;
}

// 销毁内存池
void destroyMemoryPool(MemoryPool* pool) {
    if (pool != NULL) {
        free(pool->freeList);
        free(pool);
    }
}

int main() {
    MemoryPool* pool = createMemoryPool(sizeof(MyStruct), 100);
    if (pool == NULL) {
        return 1;
    }

    MyStruct* struct1 = (MyStruct*)allocateFromPool(pool);
    if (struct1 != NULL) {
        struct1->value = 42;
        strcpy(struct1->str, "Hello, Memory Pool!");
        // 使用struct1
        freeToPool(pool, struct1);
    }

    destroyMemoryPool(pool);
    return 0;
}

方法二:使用 posix_memalign 分配内存并按页对齐

posix_memalign 函数可以分配按指定字节数对齐的内存,通常可以按页对齐(例如4096字节)。这样分配的内存块在释放后,更容易被合并,从而减少内存碎片化。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// 定义一个结构体
typedef struct {
    int value;
    char str[1000];
} MyStruct;

int main() {
    MyStruct* struct1;
    int ret = posix_memalign((void**)&struct1, getpagesize(), sizeof(MyStruct));
    if (ret != 0) {
        perror("posix_memalign");
        return 1;
    }
    struct1->value = 42;
    strcpy(struct1->str, "Hello, Aligned Memory!");
    // 使用struct1
    free(struct1);
    return 0;
}