Program crashes when trying to free a 2D dynamic allocated array - c

In general it is difficult to understand what and why is happening.
In the beginning of the program I declare two 2D dynamic arrays (all the arrays used in the program have the same dimensions):
int **initial_array;
int **new_array;
Then I allocate the necessary memory:
//dynamic allocate arrays (1st Dimension)
initial_array = calloc(N,sizeof(int));
new_array = calloc(N,sizeof(int));
//check if the memory has been allocated correctly
if (initial_array==NULL || new_array==NULL)
{
printf("Error allocating memory!\n"); //print an error message
return 1; //return with failure
}
for (i=0;i<N;i++)
{
//dynamic allocate arrays (2nd Dimension)
initial_array[i] = calloc(P, sizeof(int));
new_array[i] = calloc(P, sizeof(int));
}
I then call a function that takes the values of the initial array, generates another 2D dynamic array, which I print (inside the function) and free (by calling another function) without a problem, and I store this array to the new_array:
new_array = create_new_array(some_data, initial_array);
Then I store the values to the initial_array:
for (i=0;i<N;i++)
{
for (p=0;p<P;p++)
{
initial_array[i][p] = new_array[i][p];
}
}
free_array_in_function(new_array);
So far so good. The problem comes when I free the arrays. The initial_array works perfectly:
//free memory
for (i=0;i<N;i++)
{
free(initial_array[i]);
}
free(initial_array);
Then, I try with the new_array but the program crashes:
//free memory
for (i=0;i<N;i++)
{
free(new_array[i]);
}
free(new_array);
ERROR: Unhandled exception at 0x102d12b4 (msvcr90d.dll) in Genetic_v1.exe:
0xC0000005: Access violation reading location 0xfeeefee8.
Any ideas why is this happening?
//Function
int **create_new_array(double *some_data, int **individuals_table)
{
int **children;
//dynamic allocate array of children (1st Dimension)
children = calloc(N,sizeof(int));
//check if the memory has been allocated correctly
if (children==NULL)
{
printf("Error allocating memory!\n"); //print an error message
return 1; //return with failure
}
for (cv01=0;cv01<N;cv01++)
{
//dynamic allocate array of Individuals (2nd Dimension)
children[cv01] = calloc(P, sizeof(int));
//check if the memory has been allocated correctly
if (children[cv01]==NULL)
{
printf("Error allocating memory!\n"); //print an error message
return 1; //return with failure
}
}
//Do some calculations
return children;
}

Because your first allocation is wrong
initial_array = calloc(N,sizeof(int));
new_array = calloc(N,sizeof(int));
should be
initial_array = calloc(N,sizeof(int *));
new_array = calloc(N,sizeof(int *));
most likely you are trying this code on 64bit OS, otherwise it could have worked acidentally.
Also you overwrite the pointer new_array you don't need to this
new_array = calloc(N,sizeof(int));
or this inside the for loop
new_array[i] = calloc(P, sizeof(int));
since you have this
new_array = create_new_array(some_data, initial_array);
And finally comment
free_array_in_function(new_array);
because you are freeing the same pointer twice. And when you try to access the arryays in
free(initial_array[i]);
you are dereferencing a pointer that was already free'd.
That is not how pointers work, once you calloc the first time you have a pointer i.e. an integer value which represents a virtual addrees to memory, if you calloc again and assign to the previous pointer, then you overwrite the address and thus cause a memory leak.
Then you free the pointer you allocated with the create_new_array function, but you can't free the first calloced pointer since you have lost the reference to it.

sizeof(int) is not same as sizeof(int *). Even sometime it might be same depending on the platform you need to use sizeof(int *) here i.e. allocate memory to hold your pointers first.
For your
int **initial_array = calloc(N,sizeof(int *));
int **new_array = calloc(N,sizeof(int *));
Later you need to allocate memory for your pointers individually.
Now you should have :
initial_array[i] = calloc(P,sizeof(int));

In free_array_in_function(new_array)you are freeing the memory that is the reason you are
getting the error. The reason you are freeing the memory twice.

Related

C11 - Realloc on array of structs fails when doing realloc twice

I'm trying to use malloc and realloc to hold an array of structs. The array should dynamically grow, size should increase by 10 struct elements every time.
Struct:
typedef struct
{
unsigned char foreign_word_[100] = {0};
unsigned char native_word_[100] = {0};
} VocabularyCouple;
In my main, I initialize the array with malloc:
VocabularyCouple* VocStruct = (VocabularyCouple*)malloc(sizeof(*VocStruct) * 10);
Increasing the size of the struct-array seems to work fine in main...
VocabularyCouple* temp = (VocabularyCouple*)realloc(VocStruct, (sizeof(VocabularyCouple) * 20));
if (temp == NULL)
{
printf("ERROR: Out of Memory\n");
return 4;
}
else
{
VocStruct = temp;
free(temp);
temp = NULL;
}
However, if I put the realloc-part into a function like this:
uint8_t resizeVoc(uint32_t new_size, VocabularyCouple **VocStruct)
{
VocabularyCouple *temp = (VocabularyCouple*)realloc(*VocStruct, (sizeof(VocabularyCouple) * new_size));
...
}
I can only call the function once. Every other call will result in this error:
HEAP[VocTest.exe]: Invalid address specified to RtlValidateHeap( 01300000, 01308500 )
Unless I'm missing something, this should be the same problem as c - Realloc an array of Structs, but I just can't get it to work.
Thank you for your help!
VocStruct = temp;
free(temp);
This is wrong, you free all memory as soon as you have allocated it. VocStruct and temp point at the same memory area. Just remove the free().
To clarify, the temp pointer is just there in case realloc fails. Had you written VocStruct = realloc(VocStruct, ... and realloc fails, then you would have overwritten the only pointer to the allocated memory with NULL and created a memory leak. But you only ever have 1 chunk of memory - even though 2 pointers point at it at the same time.

Using 'realloc()' during runtime gives crash, why? - C Language

I have an array that I want to increase the size of during runtime. I assign values to the elements of the array by using a loop, and when the index of the loop hits the number of elements of the array, I want to increase the size of the array.
What I did, actually works; I can assign values to elements of the array that I would normally not be able to assign any values to without increasing the array's size. The bad side is, it gives me a crash after the program runs and finishes smoothly. What is wrong here? Is it that maybe the memory that I try to allocate for the array is already filled?
int main()
{
int arr[3];
int num_of_elements = sizeof(arr)/sizeof(arr[0]); // This gives '3', I checked
for(i = 0; i < 10; i++)
{
if(i == num_of_elements)
{
num_of_elements = num_of_elements + 10;
realloc(arr, num_of_elements);
}
arr[i] = i+10;
printf("%d\n", arr[i]);
}
return 0;
}
Well you are invoking undefined behavior. From standard ยง7.22.3.5
void *realloc(void *ptr, size_t size);
If ptr is a null pointer, the realloc function behaves like the malloc
function for the specified size. Otherwise, if ptr does not match a
pointer earlier returned by a memory management function, or if the
space has been deallocated by a call to the free or realloc function,
the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is
unchanged.
By memory management function - it means malloc etc. arr is not dynamically allocated memory. So passing this to realloc is undefined behavior - in your case that behavior leads you to crash in program.
It would work if you do this
int *arr = malloc(sizeof(int)*3);
if( arr == NULL){
perror("Malloc failed");
exit(EXIT_FAILURE);
}
...
int *p = realloc(arr,num_of_elements*sizeof(int));
^^^^^
if(p == NULL ){
perror("realloc failed");
exit(EXIT_FAILURE);
}
arr = p;
Check how realloc is used.
The takeaways will be:-
Check the return value of realloc, malloc.
You were trying to reallocate extra 10 elements for which you need 10*sizeof(int) amount of memory.
Don't do arr = realloc(arr,SIZE) in case realloc fails you will have memory leak.
Why realloc to p after all you do arr=p annyway?
Two reasons so far
The answer to this is when realloc fails then it returns NULL now if you assign arr to NULL then you may have a situation where you lose the only reference to the previously allocated memory - leading to a memory leak. That's why we do it like this.
Note this from standard
The realloc function returns a pointer to the new object (which may
have the same value as a pointer to the old object), or a null pointer
if the new object could not be allocated.
Notice that may part - it might be the same address as before as pointed by arr or it might be different one. That explains why we should store it in some temporary pointer and then we assign it later.
You should have done this:
arr = realloc(arr, num_of_elements);
^^^^^
realloc() does not necessarily extend or shrink the allocated memory in-place, it invalidates the dynamic memory that its first argument points to and allocates new memory, while preserving the content of the previous memory.
One possible implementation is :
void* realloc(void* ptr, size_t size) {
void* ret = malloc(size);
if (ret == NULL) return ret;
if (ptr != NULL) {
memcpy(ret, ptr, /* previous size from system */);
free(ptr);
}
return ret;
}

Why dont i have to free memory from the heap when reallocating?

So i have this code:
/* Dynamic Array Reader */
/* Parameters:
* n: Number of values to be read
*
* Returns: pointer to the dynamically allocated array
*/
int *dyn_reader(unsigned int n) {
int* array = malloc(n * sizeof (int));
if (!array)
return NULL;
else {
unsigned int num_read = 0;
printf("Enter %u integers so they can be put into this array\n", n);
while (num_read < n) {
num_read += scanf("%d", array + num_read);
}
}
return array;
}
/* Add to array */
/* Parameters:
* arr: Existing array of integers
* num: number of integers in the array before the call
* newval: new value to be added
*
* Returns: pointer to the allocated array
*/
int *add_to_array(int *arr, unsigned int num, int newval) {
int* newarray = realloc(arr, (num+1) * sizeof (int)); //allocate one more space
if (newarray == NULL) //Return original array if failed to allocate
return arr;
//free(arr); //free old array -- this throws an error when i try and free up the old array
newarray[num] = newval;
return newarray;
}
int main()
{
/* testing exercise. Feel free to modify */
int *array = dyn_reader(5);
array = add_to_array(array, 5, 10);
array = add_to_array(array, 6, 100);
array = add_to_array(array, 6, 1000);
return 0;
}
As you can see, the main function calls dyn_reader which allocates enough memory to allow there to be n elements in the array. It reads in integers from the user and returns the array.
Then the main function calls add_to_array which realocates enough memory to add one addition element in the array. If it cant, it returns the original array. If the memory reallocation works, i add newval to the end of the array. In this case, i am using a new pointer to store where the newly reallocated array. How come when i try to free the old array (free(arr);), i get an error. Doesn't that pointer still point to memory on the heap and shouldnt i free it?
No, if the realloc moved to a new area of memory, then it does the "free()" for you (so make sure you don't have any other pointers pointing into that array ! ). The C standard says (at http://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html ) :
The realloc() function shall deallocate the old object pointed to by ptr
The linux man page (at https://linux.die.net/man/3/realloc) makes it more explicit :
If the area pointed to was moved, a free(ptr) is done.
If reallocation was successful, realloc() has handled freeing memory related to the earlier pointer. Note that the pointer may not have even changed.
Another problem with add_to_array() is that the calling function lacks any indication of success/failure.

Understanding realloc() in C

In this example from: http://www.cplusplus.com/reference/cstdlib/realloc/
why are there two pointers: numbers and more_numbers? Can I use:
numbers = (int*) realloc (numbers, count * sizeof(int));
if (numbers!=NULL) {
numbers[count-1]=input;
}
else {
free (numbers);
puts ("Error (re)allocating memory");
exit (1);
}
The reason that example appears a little extended is to adequately deal with a failure to realloc.
numbers = (int*) realloc (numbers, count * sizeof(int));
if (numbers!=NULL) {
numbers[count-1]=input;
}
else {
free (numbers);
This will not work in the error condition; you'll be trying to free a value which you just confirmed is NULL, which probably isn't what you intend. Additionally, you've lost the (still valid) original pointer in this case (the purpose of the more_numbers pointer in your example), losing access to the data you have there and losing the ability to release the buffer.
To see why your version is wrong, you need to realise what realloc does. It does one of two things: If there is enough memory, it will return a new pointer and the old one becomes invalid. If there isn't enough memory, it will return NULL and the old pointer stays valid and unchanged.
You must store the result of realloc into a temporary variable, and not overwrite the old pointer. The reason is that if realloc returns NULL, and you overwrote the old pointer with NULL, you lost access to your existing data. So the correct way is:
int* tmp = (int*) realloc (numbers, count * sizeof(int));
if (tmp!=NULL) {
// realloc was successful. The old value of numbers is now rubbish.
// Store the result of realloc into numbers and continue.
numbers = tmp;
numbers[count-1]=input;
}
else {
// realloc failed. The old value of numbers is unchanged but doesn't have enough
// space to store input. You need to handle the error somehow.
free (numbers);
puts ("Error (re)allocating memory");
exit (1);
}
If you had stored the realloc () result directly into numbers, the "else" branch wouldn't know the old value of numbers anymore and couldn't free that memory.
According to link http://www.cplusplus.com/reference/cstdlib/realloc/
it is written "The program prompts the user for numbers until a zero character is entered. Each time a new value is introduced the memory block pointed by numbers is increased by the size of an int."
have a look at the function realloc() in http://www.tutorialspoint.com/c_standard_library/c_function_realloc.htm
void *realloc(void *ptr, size_t size);
The function returns a pointer to the newly allocated memory, or NULL if the request fails.
ptr -- This is the pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated.If this is NULL, a new block is allocated and a pointer to it is returned by the function
size -- This is the new size for the memory block, in bytes.If it is 0 and ptr points to an existing block of memory, the memory block pointed by ptr is de-allocated and a NULL pointer is returned
So after allocating memory this function returns a void pointer and it is type-casted to an integer pointer to use in the code. So each time a code is entered the memory allocated will be incremented 1 times by the sizeof(int) and the value is stored in that area.
more_numbers is the pointer which points to the starting address of the location of the memory allocated by the realloc()
numbers is the pointer which points to the array where the inputs are stored
In case if the memory allocation fails the entire memory is de-allocated using free();
You could use a function (hope i did this right):
/// int*-argument passed by-pointer
bool Enlarge(int** input, size_t new_count, int new_val)
{
void* numbers = NULL; // local ptr
numbers = (int*) realloc (*input, new_count*sizeof(int));
if (numbers!=NULL) {
*input = (int*)numbers;
(*input)[new_count - 1] = new_val;
return true;
} else {
return false;
}
}
Use it:
int* old = (int*)malloc(sizeof(int)*2);
if (!old)
return -1;
old[0] = 11; old[1] = 22;
if (!Enlarge(&old,3,33))
{
free(old);
return -2;
}
printf("A: %d, B: %d, C: %d\n", old[0], old[1], old[2]);
if (old) { free(old); }
Just beware to pass the ptr as int** and not as int* (e.g. when specifying &old[0] instead of &old.

realloc a struct, c

I have the next struct
struct Board
{
int width;
int height;
char **board;
}
And I would like to expand the **board, meaning I need more memory and thus the call to
realloc(). So my question is how do I do that - should I call realloc() on every line in the array separatly and the call it on the entire struct?
Thanks!
Call realloc for board to increase the number of elements by 1, and then call malloc on board[height] (assuming height is the first dimension) to add a new row
You need to call malloc not realloc on board. When you instantiate an object of Board, no memory is allocated to the member board ; so it's not a question of reallocating memory, but allocating memory to board in the usual way for multidimensional arrays.
#include <stdlib.h>
int **array;
array = malloc(nrows * sizeof(int *));
if(array == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
}
Once, you've allocated memory, and then if you need to expand board (e.g. board was initially 2x2 and now you want it to be 6x6), call realloc in the same order you called malloc to initialize board.
If you want more lines, you should call realloc on board, if you want to expand lines, you need to call realloc on each line you previously allocated (e.g. board[0], board[1] etc)
If you can predict how much memory you need, it would be the best to only call it once. Doing otherwise might slow down the whole suff massively.

Resources