realloc a struct, c - 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.

Related

Using realloc to double an arrays size during runtime. Is my code correct?

I am unsure if I am using the realloc function correctly.
In my program, I first ask the user for the size of the array and allocate memory for it using malloc, then initialise it with some values.
Then I want to make the same array twice it's size, using realloc. Here is my code. Am I using realloc to resize int *A correctly?
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
printf("Enter size of array\n");
scanf("%d", &n);
int *A = (int*)malloc(n*sizeof(int)); //dynamically allocated array
for (int i = 0; i < n; i++) //assign values to allocated memory
{
A[i] = i + 1;
}
A = (int*)realloc(A, 2*sizeof(int)); //make the array twice the size
free(A);
}
When using malloc() , don't cast the return value as said here
You are not using the right size. In hereint *A = (int*)malloc(n*sizeof(int)); the size given to malloc is n*sizeof(int). If you want twice that size, you should call realloc() with n*sizeof(int)*2 instead of 2*sizeof(int)
Handle realloc() failure. In case realloc(A, new_size) fails, A == NULL and you will have memory leak. So, use a different pointer B, check if (B != NULL) and then assign A = B (old_size = new_size). If B == NULL deal with the allocation fail
In this case it's easier to double the n before malloc so you don't have the use realloc, because you know, that you gonna double the arraysize. Using realloc can slow the working of the program, because if you make it longer, and the adresses after the currently allocated memories aren't free, then the whole array will be moved. Also you have the change the last line as it was suggested before me.

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

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.

C - Free a definite Amount of Memory (char**)

I have to safely free an array: char** a; It's like a string list. I know how many char* I have in it. But I have trouble to release ALL the memory. Is there like a function that I can use like to free 20 bytes ? I tried:
for (int i = 0; i < length; i++)
if (a[i] != null)
free(a[i]); // some of a[i] ARE null, non-null have different sizes
free(a); // crashes here
but I get runtime errors with asm debugging.
Every thing in a has been malloced. For a I malloced 5 strings (each pointer 4 bytes) -> 20 bytes. How can I free the whole char** ?
You can't free 20 bytes unless you allocated 20 bytes. You can only free a block. The size of that block is specified at allocation time. For each block allocated, you need a separate de-allocation.
You can try to change the size of a block by using realloc but that's not deleting an arbitrary part of that block.
If both the array and the indicvidual items in the array have been allocated using malloc, then your approach is correct. Free each of the elements, then free the array:
char **arr = malloc (10 * sizeof (char*));
if (arr != NULL)
for (int i = 0; i < 10; i++)
arr[i] = malloc (50 + i * 10); // sizes 50, 60, 70, ..., 140
// Use the ten X-character arrays here
// (other than NULL ones from malloc failures, of course).
if (arr != NULL) {
for (int i = 0; i < 10; i++)
free (arr[i]); // Okay to free (NULL), size doesn't matter
free (arr);
}
Provided that you have properly allocated the char** array and all of the char* arrays that it contains pointer to, the code that you posted should work. What does the rest of your code look like?
There is nothing wrong with the code you've posted.
However, you can get a runtime error if you free the same piece of memory twice.
Check the rest of your code and make sure you're actually allocating all the memory in that array, and not freeing it more than once.

Resizing an array with C

I need to have an array of structs in a game I'm making - but I don't want to limit the array to a fixed size. I'm told there is a way to use realloc to make the array bigger when it needs to, but can't find any working examples of this.
Could someone please show me how to do this?
Start off by creating the array:
structName ** sarray = (structName **) malloc(0 * sizeof(structName *));
Always keep track of the size separately:
size_t sarray_len = 0;
To increase or truncate:
sarray = (structName **) realloc(sarray, (sarray_len + offset) * sizeof(structName *));
Then set the size:
sarray_len += offset;
Happy to help and hope that helps.
The realloc function can be used to grow or shrink an array. When the array grows, existing entries retain their value and new entries are uninitialized. This may either grow in-place, or if that was not possible, it may allocate a new block elsewhere in memory (and behind the scenes, copy all the values over to the new block and free the old block).
The most basic form is:
// array initially empty
T *ptr = NULL;
// change the size of the array
ptr = realloc( ptr, new_element_count * sizeof *ptr );
if ( ptr == NULL )
{
exit(EXIT_FAILURE);
}
The multiplication is because realloc expects a number of bytes, but you always want your array to have the right number of elements. Note that this pattern for realloc means you do not have to repeat T anywhere in your code other than the original declaration of ptr.
If you want your program to be able to recover from an allocation failure instead of doing exit then you need to retain the old pointer instead of overwriting it with NULL:
T *new = realloc( ptr, new_element_count * sizeof *ptr );
if ( new == NULL )
{
// do some error handling; it is still safe to keep using
// ptr with the old element count
}
else
{
ptr = new;
}
Note that shrinking an array via realloc may not actually return memory to the operating system; the memory may continue to be owned by your process and available for future calls to malloc or realloc.
From http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
/* realloc example: rememb-o-matic */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int input,n;
int count=0;
int * numbers = NULL;
do {
printf ("Enter an integer value (0 to end): ");
scanf ("%d", &input);
count++;
numbers = (int*) realloc (numbers, count * sizeof(int));
if (numbers==NULL)
{ puts ("Error (re)allocating memory"); exit (1); }
numbers[count-1]=input;
} while (input!=0);
printf ("Numbers entered: ");
for (n=0;n<count;n++) printf ("%d ",numbers[n]);
free (numbers);
return 0;
}

int matrix with pointers in C - memory allocation confusion

I'm having some issues with producing an int matrix without creating memory leaks. I want to be able to make a given (global) matrix into any size dynamically via read_matrix(). But then i want to be able to free the memory later on. So in my main method the second printf should result in a bus error since it should not have any memory allocated to it. How would i go about creating this?
int** first_matrix;
int** second_matrix;
int** result_matrix;
int** read_matrix(int size_x, int size_y)
{
int** matrix;
matrix = calloc(size_x, sizeof(int*));
for(int i = 0;i<size_x;i++) {
matrix[i] = calloc(size_y, sizeof(int));
}
for(int i = 0;i<size_x;i++) {
for(int j = 0;j<size_y;j++) {
matrix[i][j] = i*10+j;
}
}
return matrix;
}
int main(int stackc, char** stack)
{
first_matrix = read_matrix(10,10);
printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
free(*first_matrix);
free(first_matrix);
printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
}
Just because the memory has been free'd doesn't mean you can't access it! Of course, it's a very bad idea to access it after it's been free'd, but that's why it works in your example.
Note that free( *first_matrix ) only free's first_matrix[0], not the other arrays. You probably want some kind of marker to signify the last array (unless you will always know when you free the outer array how many inner arrays you allocated). Something like:
int** read_matrix(int size_x, int size_y)
{
int** matrix;
matrix = calloc(size_x, 1+sizeof(int*)); // alloc one extra ptr
for(int i = 0;i<size_x;i++) {
matrix[i] = calloc(size_y, sizeof(int));
}
matrix[size_x] = NULL; // set the extra ptr to NULL
for(int i = 0;i<size_x;i++) {
for(int j = 0;j<size_y;j++) {
matrix[i][j] = i*10+j;
}
}
return matrix;
}
Then when you're freeing them:
// keep looping until you find the NULL one
for( int i=0; first_matrix[i] != NULL; i++ ) {
free( first_matrix[i] );
}
free( first_matrix );
You need to free each row individually:
void free_matrix(int **matrix, int size_x)
{
for(int i = 0; i < size_x; i++)
free(matrix[i]);
free(matrix);
}
Freeing the memory doesn't make it go away, it just means that another allocation might grab that same chunk of memory. Whatever you put in it will still be there until something else overwrites it.
Also, you're not freeing everything you allocated. You're only freeing the array of pointers and the first row. But even if you free everything correctly, you would still have the same effect.
If you want to create a "bus error" you need to point to memory that doesn't belong to your process. Why do you want to do that anyway?
You only freed the first row (or column) of first_matrix. Write another function like this:
void free_matrix(int **matrix, int rows)
{
int i;
for(i=0; i<rows; i++)
{
free(matrix[i]);
}
free(matrix);
}
You might want to make the matrix into a struct to store it's row and column count.
I recommend using valgrind to track down unfree'd memory, as opposed to trying to make a bus error occur. It rocks for lots of other stuff as well.
Sam
You're getting memory leaks because you're freeing the first row of the matrix and the list of rows, but none of the 1 to nth rows. You need to call free in a loop.
There are a couple of alternatives, however:
- Allocate sizeof(int*)rows + rowscols*sizeof(int) bytes and use the first bytes for the row pointers. That way, you only have a single chunk of memory to free (and it's easier on the allocator, too)
- Use a struct that contains the number of rows. Then you can avoid the row list altogether (saving memory). The only downside is that you have to use a function, a macro, or some messy notation to address the matrix.
If you go with the second option, you can use a struct like this in any C99 compiler, and again only have to allocate a single block of memory (of size numints*sizeof(int)+sizeof(int)):
struct matrix {
int rows;
int data[0];
}
The concept you are missing here, is that for every calloc, there must be a free.
and that free must be applied to the pointer passed back from calloc.
I recommend you create a function (named delete_matrix)
that uses a loop to free all of the pointers that you allocate in here
for(int i = 0;i < size_x;i++) {
matrix[i] = calloc(size_y, sizeof(int));
}
then, once that is done, free the pointer allocated by this.
matrix = calloc(size_x, sizeof(int*));
The way you are doing it now,
free(*first_matrix);
free(first_matrix);
won't do what you want it to do.

Resources