You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何这段模拟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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 08:57:10