我應該構建一個資料庫,通過將元素移動到陣列的末尾來從動態分配的陣列中“洗掉”一個元素。當這種元素的塊變得足夠大時,應該重新分配記憶體以縮小陣列并永久洗掉那些無用的元素。
錯誤:
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.
I don't really get it, why am I supposed to be writing illegally 8 bytes in every malloc of the deepcopy_pet() function, and reading 8 bytes upon every assignment to one of those variables I have just malloced?
My question is formed that way, considering the quote: "Heap errors have their origins at previous memory allocations but often occur after a bunch of those...".
Any suggestions?Thank you.
Full source code is available on GitHub 
uj5u.com熱心網友回復:
最小可重現示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<string.h>
#include <unistd.h>
#define N 6
#define STRLIM 20
#define YES 1
#define NO 0
#define DOWNLIM 4 //if there are less virgin slots than these, you should realloc.POTE 0 !!
#define UPLIM 10//If virgin>=uplim , then realloc to sorten the array by log.awaitDelete.
#define DEFAULTVIRGIN 2 //dld in case of realloc coz of deletions,how much should be the virgins, dld size 2
#define EXTRA 5
//ifndef
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;
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){ //prosoxi tha diagreafontai an den paro metra.tha elegxo an exei idi desmeythei mnimi
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;
}
int new_stray(petCatalog* log){ //sigoura pernane sto log giati exo kai tin epalithesi, pros to paron den xrisimopoio tin strcompare
log->array[log->size].sex=(char*)malloc(sizeof(char)*STRLIM);
if(log->array[log->size].sex==NULL){
printf("new stray malloc sex failed\n");
exit(EXIT_FAILURE);
}
log->array[log->size].breed=(char*)malloc(sizeof(char)*STRLIM);
if(log->array[log->size].sex==NULL){
printf("new stray malloc breed failed\n");
exit(EXIT_FAILURE);
}
log->array[log->size].pet_age=(age*)malloc(sizeof(age));
if(log->array[log->size].pet_age==NULL){
printf("new stray malloc breed failed\n");
exit(EXIT_FAILURE);
}
printf("enter the sex of the animal:");
scanf("%s", log->array[log->size].sex);
printf("\nthe sex of the pet is : %s",log->array[log->size].sex);
printf("\nenter the breed of the dog:");
scanf("%s", log->array[log->size].breed);
printf("\nenter the years of the dog:");
scanf("%d", &log->array[log->size].pet_age->years);
printf("\nenter the months of the dog:");
scanf("%d", &log->array[log->size].pet_age->months);
printf("\nend of new_stray");
log->size ;
return 0;
}
int main(int argc, char const *argv[])
{
int choice;
//int idcount=0;
//int bytesize=0,onelogsize=0,
int idtoDelete=-1;
petCatalog log;
log.array=(pet*)malloc(sizeof(pet)*N);
log.cap=N;
log.size=0;
log.virginSlots=N;
log.awaitDelete=0;
while(1){
menu();
printf("Enter your choice:");
scanf("%d", &choice);
if(choice==1){
if(log.virginSlots<=DOWNLIM){
log.array=(pet*)realloc(log.array,sizeof(pet)*(log.size EXTRA));
if(log.array==NULL){
printf("failed to realloc!");
exit(EXIT_FAILURE);
}
log.cap=log.cap EXTRA;
}
log.array[log.size].id=log.size;
new_stray(&log);
printf("\nlog.size is :%d",log.size);
}else if(choice==2){
printf("\nEnter id to delete:");
scanf("%d",&idtoDelete);
delete(&log,idtoDelete);
}
log.virginSlots=log.cap-log.size-log.awaitDelete;
}//end of while
return 0;
}//end of main
uj5u.com熱心網友回復:
你的代碼太復雜了:你為什么要把pet結構放在陣列的末尾?只需釋放分配的欄位,將元素復制到位,如果低于某個閾值,則可能重新分配陣列。在這里,深度復制是矯枉過正的。為 使用分配的結構age似乎也沒有必要,并且STRLIM為字串分配位元組似乎既浪費又不安全,因為您沒有檢查原始字串長度是否至多為STRLIM-1。你應該strdup()改用。
這是一個簡化版本:
int delete(petCatalog *log, int idtoDelete) {
//search to find which log has the id to delete.
for (int i = 0; i < log->size; i ) {
if (log->array[i].id == idtoDelete) {
// free the element data
free(log->array[i].sex);
free(log->array[i].breed);
free(log->array[i].pet_age);
// copy the remaining elements over the deleted entry
memmove(&log->array[i], &log->array[i 1], (log->size - i - 1) * sizeof(log->array[i]));
log->size--;
if (log->cap - log->size >= DOWNLIM) {
// shrink the array, cannot fail.
int new_cap = log->size 2; // what ever you shrink it to.
pet *new_array = realloc(log->array, new_cap * sizeof(log->array[0]));
if (new_array != NULL) {
log->array = new_array;
log->cap = new_cap;
}
}
// no need to sort after deleting an element
return 1; // element was deleted
}
}
return 0; // element was not found
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/361320.html
標籤:c malloc heap-memory valgrind realloc
上一篇:C中結構陣列中的指標問題
