【发布时间】:2021-12-30 23:05:51
【问题描述】:
我应该构建一个数据库,通过将动态分配的数组移动到数组末尾来“删除”一个元素。当这种元素的块变得足够大时,应该重新分配内存以缩小数组并永久删除那些无用的元素。
错误:
Realloc 正在抛出:
realloc():下一个大小无效
中止
重现错误的步骤(简化): 从界面中选择删除选项。
代码(简化):
在 main() 中:
printf("\nEnter id to delete:");
scanf("%d",&idtoDelete);
delete(&log,idtoDelete);
在functions.c中:
int delete(petCatalog *log, int idtoDelete) {
//search to find which log has the id to delete.
pet temp;
int distance = 0;//between size and the pet to be deleted (temp) dld idtoDelete.
int calibration = 0;
int i = 0, j = 0;//virginslots from size-1 to thee first that awaits to be deleted dld virgin slots
for (i = 0; i < log->size; i++) {
if (log->array[i].id == idtoDelete) {
//move toDelete to my temp
deepcopy_pet(&temp, &log->array[i], YES);
log->virginSlots = log->size - i;
//crerate a gap and fill the gap by overwriting
distance = log->size - idtoDelete;
calibration = distance + idtoDelete;
for (j = i + 1; j < calibration; j++) {
deepcopy_pet(&log->array[j - 1], &log->array[j], NO);
}
log->size--;
//temp to cap
deepcopy_pet(&log->array[log->cap], &temp, YES);
log->awaitDelete++; //all good till here
log->virginSlots = log->cap - log->awaitDelete - log->size;
if (log->virginSlots <= DOWNLIM) {
log->cap = log->cap - log->awaitDelete;//meaning dump everything after: size+virginslots
log->array = realloc(log->array, log->cap * sizeof(pet));
if (log->array == NULL) {
printf("deletion failed to realloc");
exit(EXIT_FAILURE);
}
} else if (log->virginSlots >= UPLIM) {
log->array = realloc(log->array, sizeof(pet) * (log->size) + DEFAULTVIRGIN);
if (log->array == NULL) {
printf("\nfailed to realloc cause of UPLIM");
exit(EXIT_FAILURE);
}
log->cap = log->size + DEFAULTVIRGIN;
}
}
//sort the array by breed again
}
return 0;
}
int deepcopy_pet(pet *dest, pet *source, int mallocDest) {
if (mallocDest == YES) {
dest->sex = (char*)malloc(sizeof(char) * STRLIM);
if (dest->sex == NULL) {
printf("failed to malloc dest->breed");
exit(EXIT_FAILURE);
}
dest->breed = (char*)malloc(sizeof(char) * STRLIM);
if (dest->breed == NULL) {
printf("failed to malloc dest->breed");
exit(EXIT_FAILURE);
}
dest->pet_age = (age*)malloc(sizeof(age));
if (dest->pet_age == NULL) {
printf("failed to malloc dest->breed");
exit(EXIT_FAILURE);
}
}
dest->id = source->id;
strcpy(dest->sex, source->sex);
strcpy(dest->breed, source->breed);
dest->pet_age->years = source->pet_age->years;
dest->pet_age->months = source->pet_age->months;
return 0;
}
以及head.h中结构的描述:
typedef struct age {
int years, months;
} age;
typedef struct pet {
int id;
char *sex;
char *breed;
age *pet_age;
} pet;
typedef struct petCatalog {
pet *array;
int size;//how many of them i got
int cap;//how big is the array
//cap-count = empty_cells;
int awaitDelete;
int virginSlots;
} petCatalog;
Valgrind 输出(简化):
==1260== Invalid write of size 8
==1260== at 0x109621: deepcopy_pet (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x1094A9: delete (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x10A507: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== Address 0x4a47108 is 8 bytes after a block of size 192 alloc'd
==1260== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1260== by 0x10A3D2: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260==
==1260== Invalid read of size 8
==1260== at 0x109629: deepcopy_pet (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x1094A9: delete (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x10A507: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== Address 0x4a47108 is 8 bytes after a block of size 192 alloc'd
==1260== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1260== by 0x10A3D2: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260==
==1260== Invalid write of size 8
==1260== at 0x10965E: deepcopy_pet (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x1094A9: delete (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x10A507: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== Address 0x4a47110 is 16 bytes after a block of size 192 alloc'd
==1260== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1260== by 0x10A3D2: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260==
==1260== Invalid read of size 8
==1260== at 0x109666: deepcopy_pet (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x1094A9: delete (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x10A507: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== Address 0x4a47110 is 16 bytes after a block of size 192 alloc'd
==1260== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1260== by 0x10A3D2: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260==
==1260== Invalid write of size 8
==1260== at 0x10969B: deepcopy_pet (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x1094A9: delete (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== by 0x10A507: main (in /mnt/c/Users/georg/Desktop/projects/strays/a.out)
==1260== Address 0x4a47118 is 24 bytes after a block of size 192 in arena "client"
==1260==
valgrind: m_mallocfree.c:305 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
我真的不明白,为什么我应该在每个 malloc 中非法写入 8 个字节 deepcopy_pet() 函数,并在每次分配给这些变量之一时读取 8 个字节 我刚刚分配了?
我的问题是这样形成的,考虑到引用: “堆错误起源于以前的内存分配,但通常发生在一堆这些之后......”。
有什么建议吗?谢谢。
完整的源代码可在 GitHub here 上找到。
附:另外,一份备忘录可以帮助您(如果您愿意)了解删除变量名的算法。无论如何,它都是可选的,因为我希望您专注于堆损坏的解释。
【问题讨论】:
-
如果您使用调试信息进行编译,例如
gcc -g,valgrind 会告诉你错误访问的行号,你应该先修复这些。行号应该可以帮助您破译这是哪个特定的访问权限以及它可能有什么问题。 -
如果您在此处需要更多帮助,请发送minimal reproducible example,并将其包含在问题中。 “可根据要求提供完整源代码”并不是一个可以在几年后对某人有所帮助的问题的秘诀。
-
@dratenik,很公平,回购现已公开。你只需克隆它,编译 main.c ,选择 1 进入日志,选择 2 删除它,你马上就会看到发生了什么。
-
@BlueDiary9 ,我记得你帮过我一次,你能再做一次吗?
-
@kjohri,你能不能也用这个做点什么?
标签: c malloc heap-memory valgrind realloc