Int Array initialization after malloc - arrays

I got this little question about this int array initialization after I did memory allocation. I got below error:
"Line 7 Error: expected expression before '{' token"
This is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int *x=malloc(3*sizeof(int)); //allocation
*x={1,2,3}; //(Line 7) trying to initialize. Also tried with x[]={1,2,3}.
for(i=0;i<3;i++)
{
printf("%d ",x[i]);
}
return 0;
}
Is there any other way to initialize my array after I do memory allocation?

First of all, we must understand that the memory for array is allocated at heap memory area. Therefore we can initialize by following methods.
using memcpy function
pointer arithmetic
Above two methods preserve the memory allocation through malloc function.
But assignment through (int[]) {1,2,3} will cause memory wastage due to previous allocated heap memory.
int* x = (int*) malloc(3 * sizeof(int));
printf("memory location x : %p\n",x);
// 1. using memcpy function
memcpy(x, (int []) {1,2,3}, 3 * sizeof(int) );
printf("memory location x : %p\n",x);
// 2. pointer arithmetic
*(x + 0) = 1;
*(x + 1) = 2;
*(x + 2) = 3;
printf("memory location x : %p\n",x);
// 3. assignment, useless in case of previous memory allocation
x = (int []) { 1, 2, 3 };
printf("memory location x : %p\n",x);

Related

realloc a 2d-array with a void function in c

I am trying to modify a 2D array from a void function.
#include <stdio.h>
#include <stdlib.h>
void try_by_reference(int **arr){
*arr = realloc(*arr, sizeof *arr * 2);
}
int main(int argc, char **argv){
// declare dynamic 2d-array and allocate memory
int (*arr)[2] = malloc(sizeof *arr * 10);
// fill array
for (int i=0; i<10; i++){
arr[i][0] = i;
arr[i][1] = i+10;
}
// declare and fill a simpler dynamic array
int *tarr = malloc(sizeof(int) * 10);
for (int i=0; i<10; i++)
tarr[i] = i*2;
try_by_reference(&tarr);
try_by_reference(&arr); <-- this gets warning
free(arr);
free(tarr);
return 0;
}
Compiler says:
warning: incompatible pointer types passing 'int (**)[2]' to parameter of type 'int **'
What am I doing wrong?
Thank you!
_"I am trying to modify a 2D array from a void function."_
Here are some tips, and fixes that will allow you to update memory to an array of two pointers to int. (see comment in-line with your code)
void try_by_reference(int **arr){
//always use a temporary variable to call realloc, otherwise if failed attempt - memory leak will occur
int *tmp = realloc(*arr, 2 * sizeof(*arr));//this effectively reduces memory from original 10, to 2 instances of int
if(!tmp)//always check return of realloc, if it fails free original memory and return
{
free(*arr);
//set pointer to NULL here to provide way to test before
//freeing later in process. (See 'Reference' below)
*arr = NULL;//to prevent problems in subsequent free calls
return;
}
else *arr = tmp;
}
int main(int argc, char **argv){
// declare dynamic 2d-array and allocate memory
int *arr[2] = {NULL, NULL};//this is an array of 2 pointers to int - each
//need to be allocated
//it will result in an array shaped as array[2][10]
//after following calls to malloc.
arr[0] = malloc(10*sizeof(arr[0]));//original provides memory for 10 instances of int
if(arr[0])
{
arr[1] = malloc(10*sizeof(arr[1]));
if(arr[1])
{
// fill array
//for (int i=0; i<10; i++){
for (int i=0; i<10; i++){
//arr[i][0] = i;
//arr[i][1] = i+10;
arr[0][i] = i;//switch indices
arr[1][i] = i+10;//switch indices
}
}
}
// declare and fill a simpler dynamic array
int *tarr = malloc(sizeof(int) * 10);
for (int i=0; i<10; i++)
tarr[i] = i*2;
try_by_reference(&tarr);
//try_by_reference(&arr); <-- this gets warning
//pass address of each pointer to memory, one at a time
try_by_reference(&(arr[0]));
try_by_reference(&(arr[1]));
//To prevent UB from calling free on an already freed pointer
//test before calling free.
if(arr[0]) free(arr[0]);//need to free each of two pointers to memory
if(arr[1] free(arr[1]);//...
if(tarr) free(tarr);
return 0;
}
Reference regarding why set pointer to NULL after freeing. If the call to realloc() fails, thus resulting in freeing the original pointer, setting the pointer == NULL provides a way to test before calling free() later in process, thus avoiding the potential of invoking undefined behavior (UB).
There are several ways to create varying shapes of nD arrays memory in C, some of them easier to update memory than the form int *arr[2]. But I stay with this form to illustrate specifically a way to update it. Although it requires more rigor to access elements, for a int[2][10] implemented by pointers, I prefer creating an int *arr = malloc(2*10*sizeof(*arr));. Observe the following examples for ease of use comparisons. (using a 2D like, but of different dimensions):
int arr1[3][6] = {{1,2,3,4,5,6},{7,8,9,10,11,12},{13,14,15,16,17,18}};
//same memory as
int arr2[18] = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}};
knowing that *(arr1 + 2*6 + 5) == arr2[2][5] = 18;
*(arr1 + 0*6 + 4) == arr2[0][4] = 5;
*(arr1 + 1*6 + 0) == arr2[1][0] = 7;
// | | |_2nd index range 0 - 5
// | |_ constant -> sizeof(arr1[0]/arr1[0][0])
// |1st index range is from 0 - 2
The same is true for dynamic memory. int **arr1 and *arr2
int **arr1 //requires 7 calls to malloc/free
int *arr2 //requires 1 call to malloc/free

Having trouble with memory leak

I am trying to generate a Fibonacci sequence by allocating space for 2 elements, so I need my array a[0] and a[1] to be constantly updated until it outputs 89 as the final number.
This is my code:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a);
int main()
{
int *pointer;
//allocates space for 2 elements for pointer
pointer = (int*)malloc(2 * sizeof(int*));
//prints first two fibonacci values
printf("0 1 ");
//calls fib2 func and apsses pointer into it
fib2(pointer);
//frees pointer memory
free(pointer);
printf("\n");
return 0;
}
//generates fibonacci sequence
void fib2(int* a)
{
int i;
//allocates space for 2 elements
a = (int*)malloc(2 * sizeof(int*));
//initial fibonacci array initialized
a[0] = 0;
a[1] = 1;
//generates and calculates fibonacci sequence and prints
for(i = 2; i < 12; i++)
{
a[i] = a[i - 1] + a[i - 2];
printf("%d ", a[i]);
}
}
I tried freeing of a[] by doing free(a); but it outputs to the console like this
**edit this is the valgrind output
There are a number of problems.
Problem 1 Wrong malloc
int *pointer;
//allocates space for 2 elements for pointer
pointer = (int*)malloc(2 * sizeof(int*));
^^^^^^^^^^^^
The sizeof should be sizeof(int) as you want to allocate space for a number (2) int. Besides that you don't need the cast. A better way to write this is:
pointer = malloc(2 * sizeof *pointer);
Problem 2 You never use pointer for any thing
You do pass its value to fib2 so that its value goes into variable a. However, immediately after you do:
a = (int*)malloc(2 * sizeof(int*)); // also sizeof wrong again
so you actually overwrite whatever value that passed. Your call of fib2 could just as well be:
fib2(NULL);
In other words: Don't do malloc both in main and in fib2. Select one place.
Problem 3 The memory in malloc'ed in fib2 are never free'ed
Your current code leaks memory because fib2 doesn't end with code like: free(a);
Problem 4 You allocate too little memory
Obviously you want 12 elements in the integer array but you only allocate ! Change code to be:
a = malloc(12 * sizeof *a);
Putting things together it could look:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a, int n);
#define NUMBERS_TO_CALCULATE 12
int main()
{
int *pointer;
//allocates space for NUMBERS_TO_CALCULATE elements for pointer
pointer = malloc(NUMBERS_TO_CALCULATE * sizeof *pointer);
if (pointer == NULL) exit(1);
//calls fib2 func and apsses pointer into it
fib2(pointer, NUMBERS_TO_CALCULATE);
// ... use pointer for other things ...
//frees pointer memory
free(pointer);
return 0;
}
//generates fibonacci sequence
void fib2(int* a, int n)
{
int i;
if (n < 2) return;
//initial fibonacci array initialized
a[0] = 0;
a[1] = 1;
//prints first two fibonacci values
printf("0 1 ");
//generates and calculates fibonacci sequence and prints
for(i = 2; i < n; i++)
{
a[i] = a[i - 1] + a[i - 2];
printf("%d ", a[i]);
}
printf("\n");
}
Note: If you don't want to use pointer for other things in main, I'll suggest that you move the malloc and free into fib2
Edit based on comments from OP
In comments OP tells about a number of restriction like:
Must use malloc
Only allowed to malloc 2 integers (I assume this also means that local variables are not allowed in fib2)
Function prototype must be void fib2(int* a)
Must print values less or equal 89
With those restrictions the program could look:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a);
int main()
{
int *pointer;
//allocates space for 2 integer elements for pointer
pointer = malloc(2 * sizeof *pointer);
if (pointer == NULL) exit(1);
//initialize fibonacci start values
pointer[0] = 0;
pointer[1] = 1;
//calls fib2 func and apsses pointer into it
fib2(pointer);
//frees pointer memory
free(pointer);
return 0;
}
//generates fibonacci sequence
void fib2(int* a)
{
//prints first two fibonacci values
printf("%d %d ", a[0], a[1]);
//generates and calculates fibonacci sequence and prints
while(a[1] < 89)
{
a[1] = a[1] + a[0]; // Calculate next number and save in a[1]
printf("%d ", a[1]); // Print it
a[0] = a[1] - a[0]; // Calculate the number for a[0]
}
printf("\n");
}

Freeing dynamic 2D array not working as expected in C

When I run code like the following:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int i, count = 0x09;
int sizei = 5, sizej = 2;
int **ary = malloc (sizei * sizeof **ary);
for (i = 0; i < sizei; i++) {
*(ary + i) = malloc (sizej * sizeof *(ary + i));
**(ary + i) = ++count;
printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
}
puts("----");
for (i = sizei - 1; i >= 0; i--) {
printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
free (*(ary + i));
}
puts("----");
free (ary);
return 0;
}
I would expect that the first half would create a 2d dynamic array of ints called ary (i.e a pointer to a dynamically allocated array of pointers, each pointing to a dynamically allocated array of ints). The 0th element of each array **(ary + i) would then be recursively assigned the current value of count.
The second half would iterate in reverse, freeing each element of ary in the reverse it was malloc'd, followed by freeing ary itself.
This appears to work fine until I try to free *(ary + 0), at which point I get a double free / corruption error. I've included the output.
0 |0x1d6f010| +a+
1 |0x1d6f018| +b+
2 |0x1d6f020| +c+
3 |0x1d6f028| +d+
4 |0x1d6f030| +e+
----
4 |0x1d6f030| +e+
3 |0x1d6f028| +d+
2 |0x1d6f020| +c+
1 |0x1d6f018| +b+
0 |0x1d6f010| +1d6f0b0+
*** Error in `./a.out': double free or corruption (out): 0x0000000001d6f030 ***
I'm curious why the 0th element of the 0th element of ary (i.e *(*(ary + 0) + 0)) or just **ary) became what looks like some memory address (only slighly) out of bounds from what's taken up by this 2d array once it got out of the first loop.
And if I get rid of the second loop and just try to free ary directly without first freeing any of its elements I get something like:
0 |0x1d6f010| +a+
1 |0x1d6f018| +b+
2 |0x1d6f020| +c+
3 |0x1d6f028| +d+
4 |0x1d6f030| +e+
----
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000001d6f010 ***
I don't understand what I've done wrong here. Would using array notation make a difference? I need any solutions to allow me to have a dynamic length of each array independant of the length of the rest of the elements of ary if at all possible. The number elements of ary wouldn't necesarily be known at compile time either. I'm using gcc 4.9 if that's relevant.
Problem 1
int **ary = malloc (sizei * sizeof **ary);
is equivalent to
int **ary = malloc (sizei * sizeof int);
If sizeof a pointer is less than sizeof(int) in your system, you end up accessing memory out of bounds.
You need to use:
int **ary = malloc (sizei * sizeof *ary);
or
int **ary = malloc (sizei * sizeof(int*));
Problem 2
*(ary + i) = malloc (sizej * sizeof *(ary + i));
needs to be
*(ary + i) = malloc (sizej * sizeof **(ary + i));
or
*(ary + i) = malloc (sizej * sizeof int);
or
ary[i] = malloc (sizej * sizeof *ary[i]);
or
ary[i] = malloc (sizej * sizeof int);
ari is pointer a to array of pointer, so size of elements are pointers. In your code, you use sizeof **ary which is an int
int **ary = malloc (sizei * sizeof **ary);
For each of the pointer to array of int elements. In your malloc for those pointers, you use sizeof *(ary+i) which is a pointer to int
*(ary + i) = malloc (sizej * sizeof *(ary + i));
sizeof(int) is not always the same as sizeof(int*). In fact, on most 64 bits systems, which I suspect is what you use, sizeof(int)==4 and sizeof(int*)==8.
My guess is that you are using such a system, and because of that, you do not allocate enough memory for the main ari pointer and you are overflowing it with values, thrashing the content of critical memory management data so future malloc() and free() call have a big chance of failing completely.

Generic bidimensional array

I want to create a bidimensional array like so:
void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * 4);
if(m==NULL)
return NULL;
for(i=0; i<nrLini; i++)
{
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
if(*(m + (i*4)) == NULL)
return NULL;
}
return m;
}
I whant to use it like this:
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
but it doesn't work. What do I do wrong?
You should use m[i] instead of *(m+i*4) and let the compiler do the arithmetic.
In addition, you should deallocate the already-allocated memory in case of a failure.
Try this instead:
void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * sizeof(void*));
if (m == NULL)
return NULL;
for (i=0; i<nrLini; i++)
{
m[i] = malloc(nrColoane * sizeOfElement);
if (m[i] == NULL)
{
while (i-- > 0)
free(m[i]);
free(m);
return NULL;
}
}
return m;
}
[not an answer to the question, but to the indented usage of the proper answer as given by others]
To access the void pointer array as an array of int, doing this
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
is not correct, as per the C-Standard only void* converts to any other pointer properly, void** doesn't necessarily. So it shall correctly be
void ** ppv = mdeclaraMatrice(n,m,sizeof(int));
int * pi = *ppv; /* Please note, there is NO casting necessary here! */
Then access the members like so:
pi[0] = 42
pi[1] = 43;
...
Which essently is the same as doing
*((int *) (pi + 0)) = 42;
*((int *) (pi + 1)) = 43;
which indeed does not make sense really as pi already is int*, so the fully correct approach (also taking into account the 2nd dimension) would be:
((int *)(ppv[0]))[0] = 42;
((int *)(ppv[0]))[1] = 43;
Which could be made usable by definging a macro:
#define GENERIC_ARRAY_ELEMENT(type, address, r, c) \
((type *)(address[r]))[c]
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42;
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43;
I will address the problem of allocation an array of void pointers and then interpreting them as an array of int pointers.
int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int));
Even assuming the allocation was completely correct the assignment and later usage of nope is undefined behavior. void** and int** have incompatible types.
What you can do is the following. Assign the void pointers one by one to an array of int pointers.
void** arrp = mdeclaraMatrice(n,m,sizeof(int));
int* arr[n] ;
for( size_t i = 0 , i < n ; i++ )
arr[i] = arrp[i] ;
And then use the arr array, When you want to free the memory you free the original pointer:
free( arrp ) ;
The problem occurs in this line:
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
You have to know that when adding a number to an address, the address will be incremented by the number times the size of the object the address points to. So if your pointer points to an object that is of size 4 bytes, and you add 1 to it, then the address will automatically be incremented by 4, not by 1. So you should abandon *4.
Also, use the sizeof operator when allocating space, because addresses (and thus pointers) can have different sizes on different processor architectures.
Actually, you don't even need your generic 2D array function if you know the powerfull VLA features of C99. To allocate a true 2D array (no index array required), you just do this:
int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray));
That's it. Accesses are just as simple:
twoDIntArray[line][column] = 42;
In this code, twoDIntArray is a pointer to an array of width integers. The malloc() call simply allocates enough space for height such line arrays. When you do the pointer arithmetic twoDIntArray[line], you add the size of line line arrays to the pointer, which produces the address of the corresponding line array. This line array is then indexed by the second array subscript [column].
Needless to say that freeing such an array is just as trivial:
free(twoDIntArray);

Convert list to array

I have functon that convert list in array:
void* list_to_array(SList* list)
{
int i;
int array_size = list_get_length(list);
void* array[array_size];
for (i = 0; i < array_size; i++)
{
array[i] = list_get_n_data(list,i);
}
return *array;
}
But when i try to test it:
int* a = (int*)list_to_array(list);
printf("%d" (int)a);
it's ok. I see first element. But when i try to get second or third element:
int* a = (int*)list_to_array(list);
a++;
printf("%d" (int)a);
I see first element + 4. if i try get third element i see first element value + 8 and etc... Why? What's wrong?
Thank you
You are returning a pointer to a stack memory location. That memory region is no longer valid once the function returns.
Also, instead of actually returning a pointer to the array, you are returning the first element in the array. The following code will return 1, not a pointer the array.
int array[] {1, 2, 3, 4};
return *array
You probably only need to make minimal changes your code to get it to work.
void** array = (void **) malloc(sizeof(void *) * array_size);
...
return array;
Just make sure that you release the memory that memory used for array when you are finished with it.
void **array = list_to_array(list);
// Use array
...
// Finished with array
free(array);
When you increase the pointer int* a by 1, it would actually increase it by sizeof(int), which is - on most systems, at least - 4.
So if
int* a = 0x40b8c438
then
a + 1
= ((void*) a) + sizeof(int)
= 0x40b8c43c
and
a + 2
= ((void*) a) + sizeof(int) * 2
= 0x40b8c440
You have three problems here. The first is trivial, you're returning the first element of the array with return *array, when what you mean is to return a pointer to the first element of the array with return array. DON'T STOP HERE! The second is that you are incrementing your pointer by 1, rather than by the size of the data you're pointing to. This will cause you to get wrong results. The third problem is much more serious:
You allocate memory for your array on this line:
void* array[array_size];
This memory is allocated on the stack, and this memory is no longer allocated when you return from the function. When you later reference this memory with the line:
int* a = (int*)list_to_array(list);
a is pointing to a region on the stack which is no longer in use. You get somewhat reasonable results with the code you have, but if you modify the stack after returning from your function, a will be pointing at the new memory. For example, if you use the following code:
int* a = (int*)list_to_array(list1);
int* b = (int*)list_to_array(list2);
printf("%d" (int)a);
You will (likely) see the first element of b. This is not guaranteed - You may also get a segmentation fault. Other code between the assignment to a and its use will also overwrite the contents of the memory you access in your printf statement.
You need to allocate your memory with the same scope as a.
// Prototype
void* list_to_array(SList* list, void* dest_array);
// C99 (Or use malloc)
void* array[list_get_length(list)];
int* a = (int*)list_to_array(list, array);
other_functions();
// Works every time!
printf("%d" (int)a);
The less serious problem is the fact that you're not incrementing your pointer by the correct amount. You need to use the sizeof() operator. Alternatively, you can access your array elements with [].
int* a = (int*)list_to_array(list, array);
printf("%d" a[1]); //Prints second element of a
a += sizeof(int) * 2;
printf("%d" (int)a); //Prints third element of a
You need to be careful with pointers, declare it this way:
int main()
{
int *array;
int i;
i = size(list);
array = list_to_array(list, i);
...
free(array);
}
int size(t_list *list)
{
int i;
i = 0;
while (list)
{
i++;
list = list->next;
}
return (i);
}
int *list_to_array(t_list *list, int size)
{
int *array;
int i;
t_list *temp;
i = 0;
if (list == NULL)
return (NULL);
array = (int*)malloc(sizeof(int) * size + 1);
temp = list;
while (temp)
{
array[i] = temp->data;
temp = temp->next;
i++;
}
return (array);
}

Resources