为何这段模拟C++ bitset的C代码有时会出现挂起现象?
C语言实现bitset时的内存越界问题修复
你的代码存在两处关键错误,直接导致了内存越界的未定义行为(表现为程序崩溃或无响应挂起):
1. malloc内存分配计算错误
你在计算柔性数组所需内存时,错误地将unsigned int的元素个数套在了sizeof()中,导致实际分配的内存远小于需求。
原代码中:
malloc(sizeof(bitset) + sizeof((init_size + sizeof(unsigned int) - 1) / sizeof(unsigned int)));
这里(init_size + sizeof(unsigned int)-1)/sizeof(unsigned int)计算的是需要的unsigned int元素个数(比如45位时结果为2),但sizeof(2)在32位系统中仅为4字节,而实际需要2个unsigned int(共8字节),直接造成柔性数组内存分配不足。
正确的计算逻辑是元素个数 × sizeof(unsigned int):
int bits_per_uint = sizeof(unsigned int) * 8; int num_uints = (init_size + bits_per_uint - 1) / bits_per_uint; bitset* bs = malloc(sizeof(bitset) + num_uints * sizeof(unsigned int));
(注:用sizeof(unsigned int)*8计算单变量存储位数,可保证代码在不同位数的系统上兼容)
2. 初始化循环的边界错误
原代码初始化循环的条件是i < (init_size +7)/8,这是按字节数循环,但data是unsigned int数组,应该按unsigned int的元素个数循环。比如45位时,(45+7)/8=6会触发6次循环,但实际仅分配了2个unsigned int元素,导致越界写入内存,触发未定义行为。
正确的循环条件应基于之前计算的num_uints:
for (int i = 0; i < num_uints; i++) { bs->data[i] = 0; }
修正后的完整代码
#include <stdio.h> #include <stdlib.h> typedef struct bitset { int size; // Number of bits unsigned int data[]; } bitset; bitset* bitset_init(int init_size) { // 计算存储init_size位所需的unsigned int数量 int bits_per_uint = sizeof(unsigned int) * 8; int num_uints = (init_size + bits_per_uint - 1) / bits_per_uint; bitset* bs = malloc(sizeof(bitset) + num_uints * sizeof(unsigned int)); if (bs == NULL) { // 新增内存分配失败检查,提升健壮性 return NULL; } bs->size = init_size; // 初始化所有unsigned int元素为0 for (int i = 0; i < num_uints; i++) { bs->data[i] = 0; } return bs; }; int main() { bitset* x = bitset_init(45); if (x != NULL) { printf("%u", x->data[0]); // 用%u打印unsigned int更规范 free(x); // 释放内存,避免内存泄漏 } return 0; }
内容的提问来源于stack exchange,提问作者DCoxshall
相关产品推荐
相关产品推荐

