【发布时间】:2020-07-07 12:51:51
【问题描述】:
我正在尝试随着输入更多值而动态增加位数组。到目前为止,我有两个问题。我已经 gdb 进入它,但在重新分配位数组时,我真的看不出我缺少什么部分,这是我看到的问题:
- Valgrind 报告了几个无效的读/写操作
- 总位数是 968 而不是 999(我假设它与 #1 有关)
==109614== Invalid read of size 4
==109614== at 0x10926F: get_bit (a.c:26)
==109614== by 0x1093EF: main (a.c:56)
==109614== Address 0x4a27094 is 0 bytes after a block of size 4 alloc'd
==109614== at 0x483BB65: calloc (vg_replace_malloc.c:762)
==109614== by 0x1092C8: init (a.c:32)
==109614== by 0x10939A: main (a.c:50)
==109614==
==109614== Invalid read of size 4
==109614== at 0x1091A6: set_bit (a.c:18)
==109614== by 0x109407: main (a.c:57)
==109614== Address 0x4a27094 is 0 bytes after a block of size 4 alloc'd
==109614== at 0x483BB65: calloc (vg_replace_malloc.c:762)
==109614== by 0x1092C8: init (a.c:32)
==109614== by 0x10939A: main (a.c:50)
==109614==
==109614== Invalid write of size 4
==109614== at 0x1091D9: set_bit (a.c:18)
==109614== by 0x109407: main (a.c:57)
==109614== Address 0x4a27094 is 0 bytes after a block of size 4 alloc'd
==109614== at 0x483BB65: calloc (vg_replace_malloc.c:762)
==109614== by 0x1092C8: init (a.c:32)
==109614== by 0x10939A: main (a.c:50)
==109614==
val=999
total bits set=968
..
#include <limits.h> /* for CHAR_BIT */
#include <string.h>
#include <stdint.h> /* for uint32_t */
#include <stdio.h>
#include <stdlib.h>
typedef uint32_t word_t; // I want to change this, from uint32_t to uint64_t
enum { BITS_PER_WORD = sizeof(word_t) * CHAR_BIT };
#define WORD_OFFSET(b) ((b) / BITS_PER_WORD)
#define BIT_OFFSET(b) ((b) % BITS_PER_WORD)
typedef struct bm_ {
word_t *bmp;
int size;
} bm;
void set_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] |= ((word_t)1 << BIT_OFFSET(n));
}
void clear_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] &= ~((word_t)1 << BIT_OFFSET(n));
}
int get_bit(word_t *words, int n) {
word_t bit = words[WORD_OFFSET(n)] & ((word_t)1 << BIT_OFFSET(n));
return bit != 0;
}
bm *init(uint32_t s) {
bm *bim = calloc(1, sizeof(bm));
bim->bmp = calloc(s, sizeof(word_t));
bim->size = s;
return bim;
}
uint32_t calc(uint32_t i) {
return (((i) + (BITS_PER_WORD)-1) / (BITS_PER_WORD));
}
int mrealloc (bm *b, int bits) {
int more = calc(bits);
uint32_t *t = realloc (b->bmp, more * sizeof(word_t));
memset (t + b->size, 0, (more - b->size) * sizeof(word_t));
b->bmp = t;
b->size = more;
}
int main(){
bm *b = init(1);
uint32_t i = 1, val = 0, cnt = 0;
for (i = 1; i < 1000; i++) {
val = i;
uint32_t bytes = calc(val);
if(bytes <= b->size) {
if(!get_bit(b->bmp, val))
set_bit(b->bmp, val);
}else{
mrealloc(b, val);
set_bit(b->bmp, val);
}
}
printf("val=%d\n",val);
for (uint32_t j=0; j < b->size; j++)
cnt+=__builtin_popcount(b->bmp[j]);
printf("total bits set=%d\n",cnt);
free (b->bmp);
free (b);
return 0;
}
【问题讨论】:
-
memset (t + b->size, 0, more - b->size);不应该是memset (t + b->size, 0, (more - b->size) * sizeof(word_t));吗? -
另外,
calc()完全忽略了抽象和硬编码32。 -
@kaylum 谢谢,这确实有帮助。虽然仍然得到一些无效的读/写
-
@unwind 感谢您的提醒,代码已更新。
-
不清楚为什么
bim->size = s;在init()(没有向上取整),而b->size = more;(向上取整)在mrealloc(),为什么要通过int?跨度>
标签: c bitmap bit realloc bitarray