C语言避免malloc/free开销

  • Post category:C

C语言中,动态内存分配(使用malloc和free函数)虽然方便,但是会存在不少开销。为了避免这些开销,可以通过一些技巧进行优化。

1. 内存池

内存池的机制是,事先申请一块固定大小的内存,并将其分成若干个固定大小的块。在需要动态分配内存时,直接从内存池中取出一个空闲块,使用完后将其放回池中。由于内存池中所有块大小固定,申请和释放时只需要维护一个索引,且不使用malloc和free函数,因此可以避免内存分配和释放所产生的开销。

以下是一个内存池的示例代码:

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

#define BLOCK_SIZE 10
#define POOL_SIZE 50

char pool[POOL_SIZE];

char* pool_alloc() {
    static int idx = 0;
    if (idx + BLOCK_SIZE > POOL_SIZE) {
        return NULL;
    }
    char* ptr = &pool[idx];
    idx += BLOCK_SIZE;
    return ptr;
}

int main() {
    char* ptrs[5];
    for (int i = 0; i < 5; i++) {
        ptrs[i] = pool_alloc();
    }
    for (int i = 0; i < 5; i++) {
        printf("%p\n", ptrs[i]);
    }
    return 0;
}

在这个代码中,我们首先定义了一个50字节大小的内存池(使用char类型是为了方便计算偏移),每次从池中取出大小为10字节的块。在主函数中我们申请了5个块,并将它们的地址打印出来。

2. 预先分配数组

另一种避免使用malloc和free函数的方法是,预先分配一个由多个元素组成的数组,使用时直接从数组中取出空闲的元素即可。这种方法可以减少内存分配的开销,但是需要在初始化时将数组分配好,因此必须提前知道需要的数组大小。

以下是一个使用数组预分配的示例代码:

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

#define MAX_OBJECTS 1024

int free_objects[MAX_OBJECTS];
int next = 0;

int get_free_object() {
    if (next >= MAX_OBJECTS) {
        return -1;
    }
    int obj = free_objects[next];
    next++;
    return obj;
}

void free_object(int obj) {
    next--;
    free_objects[next] = obj;
}

int main() {
    int* ptrs[5];
    for (int i = 0; i < 5; i++) {
        int idx = get_free_object();
        if (idx == -1) {
            ptrs[i] = NULL;
            break;
        }
        ptrs[i] = &free_objects[idx];
    }
    for (int i = 0; i < 5; i++) {
        printf("%p\n", ptrs[i]);
    }
    return 0;
}

在这个代码中,我们预先定义了一个大小为1024的int类型数组,将它全部标记为空闲。在申请内存时,使用get_free_object函数取出下一个空闲元素的索引,如果没有空闲元素则返回-1。在使用完后,将元素的索引放回数组中。在主函数中我们申请了5个元素,并将它们的地址打印出来。