Valgrind:大小为 8 的无效读取,已分配大小为 8 的块之后的字节
Valgrind: Invalid read of size 8, bytes after a block of size 8 alloc'd
一直在寻找一个简单的案例,就像我在 Stack overflow 和其他网站上找到的一样,但仍然没有找到任何东西,错误发生在第 57 行,然后也是第 47 行,valgrind 说我写了一个指向一个指针array of structures pixel,我试了一下,是不是分配内存有问题,不过好像是赋值有问题bmp_file->data = file_data
==1811== error calling PR_SET_PTRACER, vgdb might block
==1811== Invalid write of size 8
==1811== at 0x10BC02: read_bmp (bmp.c:65)
==1811== by 0x1092D7: main (main.c:12)
==1811== Address 0x4b97268 is 0 bytes after a block of size 8 alloc'd
==1811== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1811== by 0x10BB88: read_bmp (bmp.c:52)
==1811== by 0x1092D7: main (main.c:12)
==1811==
==1811== Invalid read of size 8
==1811== at 0x10BC16: read_bmp (bmp.c:67)
==1811== by 0x1092D7: main (main.c:12)
==1811== Address 0x4b97268 is 0 bytes after a block of size 8 alloc'd
==1811== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1811== by 0x10BB88: read_bmp (bmp.c:52)
==1811== by 0x1092D7: main (main.c:12)
struct bmp_image* read_bmp(FILE* stream) {
struct bmp_image* bmp_file = (struct bmp_image*)calloc(1, sizeof(struct bmp_image*));
struct bmp_header* header = read_bmp_header(stream);
if (header->type != 0x4d42) {
printf("Error: This is not a BMP file.\n");
free(bmp_file);
free(header);
return NULL;
}
struct pixel* file_data = read_data(stream, header);
bmp_file->header = header;
bmp_file->data = file_data;
if (bmp_file->header == NULL || bmp_file->data == NULL) {
printf("Error: Corrupted BMP file.\n");
if (bmp_file->header == NULL) {
free(bmp_file->header);
}
if (bmp_file->data == NULL) {
free(bmp_file->data);
}
free(bmp_file);
return NULL;
}
return bmp_file;
}
struct pixel* read_data(FILE* stream, const struct bmp_header* header) {
struct pixel* data = (struct pixel*)calloc(header->height * header->width, sizeof(struct pixel));
if (!data) {
free(data);
return NULL;
}
fseek(stream, header->offset, SEEK_SET);
unsigned short padding = header->width % 4;
for (int pixelIdx = 0; pixelIdx < header->height * header->width; pixelIdx++) {
data[pixelIdx].blue = (uint8_t)fgetc(stream);
data[pixelIdx].green = (uint8_t)fgetc(stream);
data[pixelIdx].red = (uint8_t)fgetc(stream);
if ((pixelIdx + 1) % (int)header->width != 0 || padding == 0) continue;
for (int i = 0; i < padding; i++) {
fgetc(stream);
}
}
return data;
}
void free_bmp_image(struct bmp_image* image) {
if (image == NULL) return;
free(image->header);
free(image->data);
free(image);
}
至少这个内存分配
struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof(struct bmp_image *));
不正确。看来你的意思是
struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof(struct bmp_image));
或
struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof( *bmp_file));
避免分配大小错误:
分配给引用对象的大小,而不是类型。它使代码更清晰正确,更易于审查和维护。
不需要转换。
检查分配是否成功。
示例:
// struct bmp_image* bmp_file = (struct bmp_image*)calloc(1, sizeof(struct bmp_image*));
// wrong size >----------------------------------------------^-----------------------^
struct bmp_image* bmp_file = calloc(1, sizeof bmp_file[0]);
if (bmp_file == NULL) {
fprintf(stderr, "Out-of-memory\n");
return NULL;
}
...以及代码中的其他分配。
一直在寻找一个简单的案例,就像我在 Stack overflow 和其他网站上找到的一样,但仍然没有找到任何东西,错误发生在第 57 行,然后也是第 47 行,valgrind 说我写了一个指向一个指针array of structures pixel,我试了一下,是不是分配内存有问题,不过好像是赋值有问题bmp_file->data = file_data
==1811== error calling PR_SET_PTRACER, vgdb might block
==1811== Invalid write of size 8
==1811== at 0x10BC02: read_bmp (bmp.c:65)
==1811== by 0x1092D7: main (main.c:12)
==1811== Address 0x4b97268 is 0 bytes after a block of size 8 alloc'd
==1811== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1811== by 0x10BB88: read_bmp (bmp.c:52)
==1811== by 0x1092D7: main (main.c:12)
==1811==
==1811== Invalid read of size 8
==1811== at 0x10BC16: read_bmp (bmp.c:67)
==1811== by 0x1092D7: main (main.c:12)
==1811== Address 0x4b97268 is 0 bytes after a block of size 8 alloc'd
==1811== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1811== by 0x10BB88: read_bmp (bmp.c:52)
==1811== by 0x1092D7: main (main.c:12)
struct bmp_image* read_bmp(FILE* stream) {
struct bmp_image* bmp_file = (struct bmp_image*)calloc(1, sizeof(struct bmp_image*));
struct bmp_header* header = read_bmp_header(stream);
if (header->type != 0x4d42) {
printf("Error: This is not a BMP file.\n");
free(bmp_file);
free(header);
return NULL;
}
struct pixel* file_data = read_data(stream, header);
bmp_file->header = header;
bmp_file->data = file_data;
if (bmp_file->header == NULL || bmp_file->data == NULL) {
printf("Error: Corrupted BMP file.\n");
if (bmp_file->header == NULL) {
free(bmp_file->header);
}
if (bmp_file->data == NULL) {
free(bmp_file->data);
}
free(bmp_file);
return NULL;
}
return bmp_file;
}
struct pixel* read_data(FILE* stream, const struct bmp_header* header) {
struct pixel* data = (struct pixel*)calloc(header->height * header->width, sizeof(struct pixel));
if (!data) {
free(data);
return NULL;
}
fseek(stream, header->offset, SEEK_SET);
unsigned short padding = header->width % 4;
for (int pixelIdx = 0; pixelIdx < header->height * header->width; pixelIdx++) {
data[pixelIdx].blue = (uint8_t)fgetc(stream);
data[pixelIdx].green = (uint8_t)fgetc(stream);
data[pixelIdx].red = (uint8_t)fgetc(stream);
if ((pixelIdx + 1) % (int)header->width != 0 || padding == 0) continue;
for (int i = 0; i < padding; i++) {
fgetc(stream);
}
}
return data;
}
void free_bmp_image(struct bmp_image* image) {
if (image == NULL) return;
free(image->header);
free(image->data);
free(image);
}
至少这个内存分配
struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof(struct bmp_image *));
不正确。看来你的意思是
struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof(struct bmp_image));
或
struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof( *bmp_file));
避免分配大小错误:
分配给引用对象的大小,而不是类型。它使代码更清晰正确,更易于审查和维护。
不需要转换。
检查分配是否成功。
示例:
// struct bmp_image* bmp_file = (struct bmp_image*)calloc(1, sizeof(struct bmp_image*));
// wrong size >----------------------------------------------^-----------------------^
struct bmp_image* bmp_file = calloc(1, sizeof bmp_file[0]);
if (bmp_file == NULL) {
fprintf(stderr, "Out-of-memory\n");
return NULL;
}
...以及代码中的其他分配。