dynamic allocation of array of pointers - c

The following code gives a segmentation fault. I am not able to figure out as to why. Please see..
#include <stdio.h>
#include <stdlib.h>
int main()
{
int **ptr;
int *val;
int x = 7;
val = &x;
*ptr = (int *)malloc(10 * sizeof (*val));
*ptr[0] = *val;
printf("%d\n", *ptr[0] );
return 0;
}
on debugging with gdb, it says:
Program received signal SIGSEGV, Segmentation fault.
0x0804843f in main () at temp.c:10
*ptr = (int *)malloc(10 * sizeof (*val));
Any help regarding the matter is appreciated.

int **ptr;
*ptr = (int *)malloc(10 * sizeof (*val));
First statement declares a double pointer.
Second dereferences the pointer. In order that you are able to dereference it the pointer should point to some valid memory. it does not hence the seg fault.
If you need to allocate enough memory for array of pointers you need:
ptr = malloc(sizeof(int *) * 10);
Now ptr points to a memory big enough to hold 10 pointers to int.
Each of the array elements which itself is a pointer can now be accessed using ptr[i] where,
i < 10

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **ptr;
int x;
x = 5;
ptr = malloc(sizeof(int *) * 10);
ptr[0] = &x;
/* etc */
printf("%d\n", *ptr[0]);
free(ptr);
return 0;
}

See the below program, perhaps, it helps to understand better.
#include<stdio.h>
#include <stdlib.h>
int main(){
/* Single Dimention */
int *sdimen,i;
sdimen = malloc ( 10 * sizeof (int));
/* Access elements like single diminution. */
sdimen[0] = 10;
sdimen[1] = 20;
printf ("\n.. %d... %d ", sdimen[0], sdimen[1]);
/* Two dimention ie: **Array of pointers.** */
int **twodimen;
twodimen = malloc ( sizeof ( int *) * 10);
for (i=0; i<10; i++) {
twodimen[i] = malloc (sizeof(int) * 5);
}
/* Access array of pointers */
twodimen[0][0] = 10;
twodimen[0][3] = 30;
twodimen[2][3] = 50;
printf ("\n %d ... %d.... %d ", twodimen[0][0], twodimen[0][3], twodimen[2][3]);
return 0;
}
Hope this helps.. ;).

Conceptually if you are using **ptr, then you need to alloacte memory for ptr & *ptr to defrence **ptr.
But in you case you are alloacting memory only for *ptr,if your compiler is smart enough
its alloacting memory for ptr(one pointer location) to link *ptr,hence it could able to link ptr->ptr->*ptr.Hence you are not getting Seg Fault.

include
include
int main()
{
int **ptr;
int *val;
int x = 7;
val = &x;
ptr = (int**)malloc(sizeof(int**));
*ptr = (int *)malloc(10 * sizeof (*val));
*ptr[0] = *val;
printf("%d\n", *ptr[0] );
return 0;
}
Above would work.
You can find the difference and understand the reason as well.
Bottom line you were de-referencing **ptr without allocating memory to it.

Related

how do I dereference a pointer which I got from a function in c?

#include <stdio.h>
#include <stdlib.h>
int* CreateArray(int length){
int arr[length];
int i;
for(i=0; i < length; ++i){
arr[i] = -25;
int* ptr = &arr[i];
printf("%p \n",ptr);
printf("%d \n",*ptr);
}
printf("%d \n",arr[0]);
int* location = &arr;
return location;
}
void main()
{
int* arr = CreateArray(10);
printf("pointer here is %p \n",arr);
int num = *arr;
printf("%d",num);
}
when i run the program i want num to be equal to arr[0] which was declared in the function but it doesn't do that for some reason
The array arr is local to the function CreateArray and not marked as static, so it will deleted on returning from the function and cannot be used after that.
To avoid this, you should allocate arrays dynamically.
Also note that &arr is int(*)[length], so it is not good to assign that to a variable of type int*.
int* CreateArray(int length){
int *arr = malloc(sizeof(*arr) * length); /* allocate dynamically */
if (arr == NULL) exit(1); /* check if allocation succeeded */
int i;
for(i=0; i < length; ++i){
arr[i] = -25;
int* ptr = &arr[i];
printf("%p \n",(void*)ptr); /* void* should be passed for %p */
printf("%d \n",*ptr);
}
printf("%d \n",arr[0]);
int* location = arr; /* assign arr, not &arr */
return location;
}
Your function is returning a pointer created inside the function, and it will be deinitialized when the function is popped from the stack. This is called dangling pointer.
If you want to return a pointer, you have to create it on the heap:
int* arr = malloc(sizeof(*arr) * length);;
But pay attention, now you have to manage the garbage!

Why does a pointer to a multidimensional array return segmentation fault when accessed after passing the pointer to a function?

So I don't really know what this problem is really called so searching and googling leads to different answers which does not answer my question.
This is the code:
#include <stdio.h>
#include <stdlib.h>
void gen_matrix(int **array, int rm, int cm) {
// int ** array;
int r, c;
array = (int **) malloc(sizeof(int *) * rm);
for (int r = 0; r < rm; ++r) {
array[r] = (int *) malloc(sizeof(int) * cm);
for (int c = 0; c < cm; ++c) {
array[r][c] = 1;
} // c
} // r
}// gen_matrix
int main() {
int **a;
gen_matrix(a, 2, 2);
printf("%d", a[0][0]);
return 0;
}
The problem is that printf() in main() returns Segmentation Fault. What I found out is that the address that the pointer a in main() points to does not change when malloc() is used inside gen_matrix().
In gen_matrix(), I can access the array just fine, but after I return to main(), the pointer a does not point to the array malloc() created.
Thank you.
You are losing the update to array when gen_matrix() returns, because you are not passing it the address of a. You could add an extra indirection level by passing in the address of a to gen_matrix(), but it would be cleaner to just have gen_matrix() return the malloced address and assign it to a in main():
int **gen_matrix(int rm, int cm) {
int ** array;
array = malloc(sizeof(*array) * rm);
for (int r = 0; r < rm; ++r) {
array[r] = malloc(sizeof(*(array[r])) * cm);
for (int c = 0; c < cm; ++c) {
array[r][c] = 1;
} // c
} // r
return array;
}// gen_matrix
int main() {
int **a;
a = gen_matrix(2, 2);
printf("%d", a[0][0]);
return 0;
}
Also, it's not a good idea to cast the return from malloc() and it is preferable to dereference the pointer the memory is being assigned to to get the proper size for sizeof().
And you should of course free() the memory before exiting.
When you call your function the parameter int ** array is the "array itself". What you need is a reference to it, either with one more level of pointer indirection or a C++-style reference. So, what you do is you modify the function to accept a triple-pointer:
void gen_matrix(int ** * array, int rm, int cm) {
and when you call it you also get the address of the "pointer to the matrix":
gen_matrix(&a, 2, 2);
of course you have to modify the code in the function to take care of that extra indirection:
*array = (int **) malloc(sizeof(int *) * rm);
and in the other two places as well.

changing adress of pointer created using malloc

I am trying to understand how malloc and pointer works.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p;
int b = 15;
p = (int *)malloc(sizeof(int) * 10);
for (int i = 0; i < 5; i++) {
p + i = &b;
}
}
The above code gives error
expression is not assignable
p + i = &b;
As far as I understand, malloc gives the starting address of the memory allocated in heap which I typecast to hold the address of integers. So technically, p + i should be able to hold any integer address, but the code throws an error. Can you please explain why this is wrong.
Thanks
The line of code p = (int *)malloc(sizeof(int) * 10); means that the pointer p is assigned the address of the first element of the dynamically allocated array with malloc(),which has allocated an int array consisting of 10 elements.
If you want to assign 5 of these elements the value of b then you write:
for (int i = 0; i < 5; i++) {
p[i] = b;
}
If however you want an array of 10 integer pointers and want to assign 5 of them the address of b,then you write:
int **pointer = (int **)malloc(sizeof(int *) * 10);
for (int i = 0; i < 5; i++) {
pointer[i] = &b;
}
Don't forget to free dynamically allocated memory when you finish.
p + i is pointing to an address on your memory, the same as &(p[i]). You can't change the address of the memory, so that's why the compiler is saying the expression is not assignable.
If you want to save an int on that address you need to use *(p+i) = b.
But if you want to save the address of an int you need an array which holds int*, so you need to declare p as an int** and allocate its memory with the sizeof(int*). That way your code would look like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
int **p;
int b = 15;
p = (int**)malloc(sizeof(int*) * 10);
for (int i = 0; i < 5; i++) {
*(p + i) = &b;
}
}

Why does this need to be malloc'd?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int * p = malloc(sizeof(int));
*p = 10;
*p += 10;
printf("%d", *p);
}
It gives me the correct value if it is malloc'd but a bus error if I just declare it as:
int main(){
int * p;
*p = 10;
*p += 10;
printf("%d", *p);
}
An uninitialized pointer is just that; uninitialized. Where do you expect it to point? It's value is indeterminate and reading/writing it results in undefined behavior.
It doesn't have to refer to dynamically allocated memory (malloc), but it does have to refer to valid memory. For example, this would be fine:
int main(void)
{
int x;
int *p = &x;
*p = 10;
*p += 10;
printf("%d", *p);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *ptr;
//*ptr=123; Error here....Becuase it is like trying to store
//some thing into a variable without creating it first.
ptr=malloc(sizeof(int)); // what malloc does is create a integer variable for you
// at runtime and returns its address to ptr,
// Which is same as if you assingned &some_variable
// to ptr if it had been already present in your program.
return 0;
}

C: Allocating memory confusion

For this code
#include <stdlib.h>
#include <stdio.h>
int *f (int n)
{
int *ptr = malloc (sizeof (int));
*ptr = n;
return ptr;
}
int main()
{
int i;
int **ptr = malloc (sizeof (int *));
ptr[0] = f (0);
for (i = 0; i < 5; ++i)
{
ptr = realloc (sizeof (int *) * (i + 2));
ptr[i + 1] = malloc (sizeof (int));
ptr[i + 1] = f (i + 1);
}
for (i = 0; i < 5; ++i)
{
printf ("%d\n", *ptr[i]);
free (ptr[i]);
}
free (ptr);
return 0;
}
does program allocate twice than it is needed?
Yes, You don't need the malloc in main as it is immediately overwritten on the next line and you leak that memory. Is this a homework question?
EDIT for question change
This is now leaking memory in an odd way.
The first few lines aren't leaking but when you get into the loop you're allocating and assigning randomly. (As a first, realloc takes as it's first arguement a pointer to reallocate, so you're missing ptr in there)
Now you're allocating ptr to be of size 2, then 3 then 4 etc... up to 6. And then immediately leaking that memory as you overwrite the pointer with the call to f()
You could write that all like this:
int i;
int **ptr = malloc (sizeof(int*) * 6);
for (i = 0; i < 6; ++i)
{
ptr[i] = f(i);
}
for (i = 0; i < 6; ++i)
{
printf ("%d\n", *ptr[i]);
free (ptr[i]);
}
free (ptr);
return 0;
As an aside, you should in general try not to allocate memory too often, it is relatively slow. If you can use the stack you should, and if not, try and allocate all the memory you need up front, calling realloc in a loop is a bad idea and should be avoided.
In this specific case you don't need a pointer to a pointer, you could have just allocated one array of 6 integers, with int* array = malloc(sizeof(int) * 6) and then array[0] = 0; which would be easier and better.
Yes, it does allocate twice the needed memory. Also, the value of "ptr" in main is overwrite by return of "f" so you don't even have a chance to free it. You could remove the call to malloc in "main":
int main()
{
int *ptr = f (3);
printf ("%d\n", *ptr);
free (ptr);
return 0;
}

Resources