Here's a structure of set that I've written:
struct state_set
{
struct state ***state_array;
size_t *slot_sizes;
size_t *slot_memory;
};
Here's an initializer:
struct state_set *state_set_init()
{
struct state_set *new_set =
malloc(sizeof(struct state_set));
new_set->state_array = malloc(ARRAY_SIZE * sizeof(struct state**));
new_set->slot_sizes = malloc(ARRAY_SIZE * sizeof(size_t));
new_set->slot_memory = malloc(ARRAY_SIZE * sizeof(size_t));
for (int i = 0; i < ARRAY_SIZE; i++)
{
new_set->slot_sizes[i] = 0;
new_set->slot_memory[i] = INITIAL_SLOT_SIZE;
}
for (int i = 0; i < ARRAY_SIZE; i++)
{
new_set->state_array[i] =
malloc(new_set->slot_memory[i] * sizeof(struct state*));
error_validate_pointer(new_set->state_array[i]);
}
return new_set;
}
And there's a resizing function that causes memory errors:
void state_set_resize_slot(struct state_set *set, int slot_i)
{
struct state **to_resize = set->state_array[slot_i];
to_resize =
realloc(to_resize, set->slot_memory[slot_i] * 2 * sizeof(struct state*));
error_validate_pointer(to_resize);
set->slot_memory[slot_i] *= 2;
}
The question is - why is state_set_resize_slot() not working? I can't see any error with this realloc, and I've been staring at this code for at least an hour. (And clearly the realloc is the cause of all my trouble). Or maybe the resizing function is written well and I should look for errors elsewhere?
EDIT:
If someone wants to take a peek at full code, it's available here: http://pastebin.com/bfH3arDi (hash function returns 1 instead of h because I'm testing collisions, also initializer and destructor function are outdated, now I'm malloc'ing the data for slot_memory and slot_sizes instead of using stack).
And here's valgrind output from running the program that adds several states to set (error is at about third resize):
==20979== Invalid write of size 8
==20979== at 0x400C21: state_set_add (state_set.c:93)
==20979== by 0x400781: main (main.c:22)
==20979== Address 0x51f2320 is 0 bytes inside a block of size 40 free'd
==20979== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20979== by 0x4009CD: state_set_resize_slot (state_set.c:54)
==20979== by 0x400B23: state_set_add (state_set.c:78)
==20979== by 0x400781: main (main.c:22)
==20979==
==20979== Invalid free() / delete / delete[] / realloc()
==20979== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20979== by 0x4009CD: state_set_resize_slot (state_set.c:54)
==20979== by 0x400B23: state_set_add (state_set.c:78)
==20979== by 0x4007B2: main (main.c:23)
==20979== Address 0x51f2320 is 0 bytes inside a block of size 40 free'd
==20979== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20979== by 0x4009CD: state_set_resize_slot (state_set.c:54)
==20979== by 0x400B23: state_set_add (state_set.c:78)
==20979== by 0x400781: main (main.c:22)
==20979==
a.out: state_set.c:20: error_validate_pointer: Assertion `ptr != ((void *)0)' failed.
In your function you are taking the pointer into to_resize, then you realloc the memory, but you never set the new pointer back to the set->state_array[slot_i], so it is lost and you keep on using the old, already freed memory space and will point outside its bounds.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With