segmentation fault looping through 2-D pointer array - c

I'm getting a segmentation fault when I loop through this 2-d pointer array
declaration:
char **addr;
addr=malloc((y)*sizeof(char)); //y is 3
for(i=0;i<y;i++)
{
*(addr+i)=malloc(x*sizeof(char)); //x is 100
}
independent access works:
*(*(addr+2)+0)='a';
printf("%c\n",*(*(addr+2)+0));
loop returns a segmentation fault at addr[2][0] regardless of what y and x are
for(j=0;j<x;j++)
{
for(i=0;i<y;i++)
{
printf("%d %d\n",j,i);
*(*(addr+j)+i)='a';
}
}

addr=malloc((y)*sizeof(char));
must be replaced by
addr = malloc(y * sizeof(char *));

Try using the X *x = malloc(sizeof *x) idiom when allocating memory :
addr = malloc(y * sizeof *addr);
So the result of sizeof actually refers to the type of the data you're pointing to :
sizeof *addr == sizeof(char *)

The previous answers are good. This is just an alternative you may consider. It is a way to do what you are doing, that also will help to free the memory properly (which is sometimes a pain with multi-pointer arrays)
Define functions to do the work:
char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
int i;
a = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(sizeof(char)*maxStrLen+ 1, sizeof(char));
}
return a;
}
void freeMemory(char ** a, int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(a[i]) free(a[i]);
free(a);
}
Then you can simply call these functions with parameters you have created for any number of strings, with a max string length, then free the same with a pre-configured function.
So your code would look like this:
char **addr;
addr = allocMemory(addr, 100, 3); //100 strings of max length == 3
Then, when you are done with addr:
freeMemory(addr, 100); //free 100 strings, and associated pointers.

Related

I get trash values when trying to print them and a segmentation fault [duplicate]

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 4 years ago.
I wrote this simple code to test a bigger implementation I have and I get trash values plus a seg fault. One solution is to declare int* a and int* b as global and take out the arguments of fill. My question is, what is the consideration of memory handling in both cases, and why does it throw an error?
#include <stdio.h>
#include<stdlib.h>
#define LENGTH 4
void fill(int* a, int* b){
a = (int*) malloc(LENGTH * sizeof(int));
b = (int*) malloc(LENGTH * sizeof(int));
for(int i=0; i< LENGTH;i++){
a[i]=i;
b[i]=i+10;
}
}
void printArray(int* a, int* b){
for(int i = 0 ; i < LENGTH; i++)
printf("%d\n",a[i] );
for(int i = 0 ; i < LENGTH; i++)
printf("%d\n",b[i] );
}
int main(){
int* a;
int* b;
fill(a,b);
printArray(a,b);
}
You should pass pointers to pointers as arguments to the fill function so you can effectively modify the pointers a and b.
void fill(int** a, int** b){
*a = malloc(LENGTH * sizeof(int));
(*a)[i]=i;
fill(&a,&b);
Whenever you send args to a function in c they are always sent by value.
here, you send by value the addresses that a and b point to - they are uninitialized- so junk values.
When you use malloc- it returns a pointer to an address on the heap.
in your function the local values of a and b change. but in your main function they do not. if you want your function to change the address the pointers are pointing to in outside of the function you must send **a and **b. now when you change the address for a : * a= malloc() you change the value the pointer is holding. So now your a and b pointers will hold the new addresses allocated.
void fill(int** a, int** b)/*here you send by value the pointers addrsses */
{
int* aptr = NULL;
int* bptr = NULL;
*a = (int*) malloc(LENGTH * sizeof(int));/*update the value pointe a is pointing to */
*b = (int*) malloc(LENGTH * sizeof(int));
aptr = *a;
bptr = *b;
for(int i=0; i< LENGTH;i++){
aptr[i]=i;
bptr[i]=i+10;
}
}

New beginner for dynamically allocated Array. Why do I have segmentation fault here?

I use nested data structure for fibonacci, but I have a segmentation fault 11.
void fib(int **fib_array, int n){
fib_array = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++){
fib_array[i] = malloc(sizeof(int));
}
for(int i = 0; i < n; i++){
if (i <= 1){
fib_array[i][0] = i;
}
else{
fib_array[i][0] = fib_array[i - 2][0] + fib_array[i - 1][0];
}
}
}
int main(int argc, char **argv) {
/* do not change this main function */
int count = strtol(argv[1], NULL, 10);
int *fib_sequence;
fib(&fib_sequence, count);
for (int i = 0; i < count; i++) {
printf("%d ", fib_sequence[i]);
}
free(fib_sequence);
return 0;
}
you are being too complicated. You just need a single malloc
*fib_array = malloc(n * sizeof(int));
and remove you second indexings [0] from everywhere
The consfusion comes from **int. This looks like a multi dim array. Its not - its declared ** so that you can set the value in the caller. A simpler exampe will help
void Make42(int* v)
{
*v = 42;
}
int main()
{
int myv = 0;
Make42(&myv);
// now myv == 42
}
The * in the arg list is so that Make42 can 'reach out' and modify what was passed to it (myv in this case)
In your code the ** on fib array is there for the same purpose. you could have done (In know you werent allowed to by the test definition )
int *fib(int n){
int *fib_array = malloc(n * sizeof(int));
......
return fib_array;
}
and in main
fib_sequence = fib(count);
this makes it much clearer that you are really manipulating a simple array
pm100 is right, but a little short for answering to a beginner...
At first, you have passed a pointer to a pointer. If you want the original pointer to contain a value, you need to dereference the pointer to pointer:
*fib_array = ...
By assigning to the pointer only (as you did in your code), you do not modify the orignial pointer (fib_sequence in main) at all. And as you have not initialised it, it might point to anywhere, thus the segmentation fault when you try to print the values of it.
Then why an array of pointers to individually stored values? You can use a contiguous array of ints, which you get by
*fib_array = malloc(n * sizeof(int));
OK, further usage won't be too nice ((*fib_array)[i] = ...), so I recommend a temporary variable instead:
int* fa = malloc(n * sizeof(int));
// now fill in the values comfortably:
fa[i] = ...;
// finally, assign the pointer to the target:
*fib_array = fa;
Side note: always check the result of malloc, it could be NULL:
fa = ...
if(fa)
// assign values
else
// appropriate error handling
In your concrete case, you could omit the else branch in your function and check your pointer outside within main function.
By the way, a simple return value would have made your live easier, too:
int* fib(int n)
{
int* fib_array = malloc(n * sizeof(int*));
// ...
return fib_array;
}
Notice: no need for pointer to pointer... Usage:
int* fib_sequence = fib(count);

allocating space for pointer to array of pointers

Good day. I have this: MAP_ITEM **map what I think is pointer to array of pointers (correct me if I am wrong please) and I have to allocate space for it. I can allocate space using malloc for 1 pointer, but have no idea how to do this. help would be really appreciated.
Here is an example, written for use with char **, but you can modify for your purposes:
char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
int i;
a = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(sizeof(char)*maxStrLen + 1, sizeof(char));
}
return a;
}
call it like this: (for array of 10 strings, each having maximum of 79 characters (leave one for NULL term)
char **arrayOfString;
arrayOfString = allocMemory(arrayOfString, 10, 80);
//
You also need to free memory created with allocMemory
void freeMemory(char ** a, int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(a[i]) free(a[i]);
free(a);
}
Call it like this:
freeMemory(arrayOfStrings, 10);
Import the stdlib.h
Then use the malloc function.
Where is an example for a one dimentional array:
int* my_in_array = (int*) malloc(sizeof(int) * size_of_my_array);
Note that malloc receives the number of bytes you want to allocate, so sizeof will tell you how many bytes a datatype will need (in this case an int, but it can be used for chars, structures, ...) and then I multiplicate it by size_of_my_array, wich is the number of elements of my array.
Now, just try to se this for you case.

Why am I getting segmentation fault for malloc() while using pointer to pointer?

I don't understand why this works:
void main() {
int * b;
b = (int *)malloc(sizeof(int));
*b = 1;
printf("*b = %d\n", *b);
}
while this does not (gets segmentation fault for the malloc()):
void main() {
int ** a;
int i;
for (i = 0; i<= 3; i++) {
a[i] = (int*)malloc(sizeof(int));
*(a[i]) = i;
printf("*a[%d] = %d\n", i, *(a[i]));
}
}
since I find a[i] is just like b in the first example.
BTW, a[i] is equal to *(a+i), right?
You need to allocate memory for a first, so that you can access its members as a[i].
So if you want to allocate for 4 int * do
a = malloc(sizeof(int *) * 4);
for (i = 0; i<= 3; i++) {
...
}
or define it as array of integer pointers as
int *a[4];
a is a 2 dimensional pointer, you have to allocate both dimension.
b is a 1 dimensional pointer, you have to allocate only one dimension and that's what you're doing with
b = (int *)malloc(sizeof(int));
So in order the second example to work you have to allocate the space for the pointer of pointer
void main() {
int ** a;
int i;
a = (int**)malloc(4*sizeof(int*));
for (i = 0; i<= 3; i++) {
a[i] = (int*)malloc(sizeof(int));
*(a[i]) = i;
printf("*a[%d] = %d\n", i, *(a[i]));
}
The allocated pointer is written to uninitialized memory (you never set a to anything), causing undefined behavior.
So no, it's not at all equivalent to the code in the first example.
You would need something like:
int **a;
a = malloc(3 * sizeof *a);
first, to make sure a holds something valid, then you can use indexing and assign to a[0].
Further, this:
a[i] = (int*)malloc(sizeof(int));
doesn't make any sense. It's assigning to a[i], an object of type int *, but allocating space for sizeof (int).
Finally, don't cast the return value of malloc() in C.
actually malloc it's not that trivial if you really want safe and portable, on linux for example malloc could return a positive response for a given request even if the actual memory it's not even really reserved for your program or the memory it's not writable.
For what I know both of your examples can potentially return a seg-fault or simply crash.
#ruppells-vulture I would argue that malloc is really portable and "safe" for this reasons.

Allocate memory 2d array in function C

How to allocate dynamic memory for 2d array in function ?
I tried this way:
int main()
{
int m=4,n=3;
int** arr;
allocate_mem(&arr,n,m);
}
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*arr[i]=(int*)malloc(m*sizeof(int));
}
But it doesn't work.
Your code is wrong at *arr[i]=(int*)malloc(m*sizeof(int)); because the precedence of the [] operator is higher than the * deference operator: In the expression *arr[i], first arr[i] is evaluated then * is applied. What you need is the reverse (dereference arr, then apply []).
Use parentheses like this: (*arr)[i] to override operator precedence. Now, your code should look like this:
void allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n*sizeof(int*));
for(int i=0; i<n; i++)
(*arr)[i] = (int*)malloc(m*sizeof(int));
}
To understand further what happens in the above code, read this answer.
It is important that you always deallocate dynamically allocated memory explicitly once you are done working with it. To free the memory allocated by the above function, you should do this:
void deallocate_mem(int*** arr, int n){
for (int i = 0; i < n; i++)
free((*arr)[i]);
free(*arr);
}
Additionally, a better way to create a 2D array is to allocate contiguous memory with a single malloc() function call as below:
int* allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n * sizeof(int*));
int *arr_data = malloc( n * m * sizeof(int));
for(int i=0; i<n; i++)
(*arr)[i] = arr_data + i * m ;
return arr_data; //free point
}
To deallocate this memory:
void deallocate_mem(int*** arr, int* arr_data){
free(arr_data);
free(*arr);
}
Notice that in the second technique malloc is called only two times, and so in the deallocation code free is called only two times instead of calling it in a loop. So this technique should be better.
Consider this: Just single allocation
int** allocate2D(int m, int n)
{
int **a = (int **)malloc(m * sizeof(int *) + (m * n * sizeof(int)));
int *mem = (int *)(a + m);
for(int i = 0; i < m; i++)
{
a[i] = mem + (i * n);
}
return a;
}
To Free:
free(a);
If your array does not need to be resized (well, you can, but il will be a bit more complicated), there is an easier/more efficient way to build 2D arrays in C.
Take a look at http://c-faq.com/aryptr/dynmuldimary.html.
The second method (for the array called array2) is quite simple, less painful (try to add the tests for mallocs' return value), and way more efficient.
I've just benchmarked it, for a 200x100 array, allocated and deallocated 100000 times:
Method 1 : 1.8s
Method 2 : 47ms
And the data in the array will be more contiguous, which may speed things up (you may get some more efficient techniques to copy, reset... an array allocated this way).
Rather allocating the memory in many different block, one can allocate this in a consecutive block of memory.
Do the following:
int** my2DAllocation(int rows,int columns)
{
int i;
int header= rows *sizeof(int *);
int data=rows*cols*sizeof(int);
int ** rowptr=(int **)malloc(header+data);
if(rowptr==NULL)
{
return NULL:
}
int * buf=(int*)(rowptr+rows);
for(i=0;i<rows;i++)
{
rowptr[i]=buf+i*cols;
}
return rowptr;
}
That is an unnecessarily complicated way of allocating space for an array. Consider this idiom:
int main(void) {
size_t m = 4, n = 3;
int (*array)[m];
array = malloc(n * sizeof *array);
free(array);
}
I have tried the following code for allocating memory to 2 dimensional array.
#include<stdio.h>
#include<malloc.h>
void main(void)
{
int **p;//double pointer holding a 2d array
int i,j;
for(i=0;i<3;i++)
{
p=(int**)(malloc(sizeof(int*)));//memory allocation for double pointer
for(j=(3*i+1);j<(3*i+4);j++)
{
*p = (int*)(malloc(sizeof(int)));//memory allocation for pointer holding integer array
**p = j;
printf(" %d",**p);//print integers in a row
printf("\n");
p++;
}
}
}
Output of the above code is:-
1 2 3
4 5 6
7 8 9
In order to understand 2 dimensional array in terms of pointers, we need to understand how it will be allocated in memory, it should be something like this:-
1 2 3
1000 --> 100 104 108
4 5 6
1004 --> 200 204 208
7 8 9
1008 --> 300 304 308
from the above, we understand that, when we allocate memory to pointer p which is a double pointer, it is pointing to an array of integers, so in this example, we see that the 0x1000 is pointer p.
This pointer is pointing to integer pointer *p which is array of integers, when memory is allocated inside the inner for loop, during first iteration the pointer is 0x100 which is pointing to integer value 1, when we assign **p = j. Similarly it will be pointing to 2 and 3 in the next iterations in the loop.
Before the next iteration of the outer loop, double pointer is incremented, inside the next iteration, as is seen in this example the pointer is now at 0x1004 and is pointing to integer pointer which is an array of integers 4,5,6 and similarly for the next iterations in the loop.
Try the following code:
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*(arr+i)=(int*)malloc(m*sizeof(int));
}
2d Array dynamically array using malloc:
int row = 4;
int column = 4;
int val = 2;
// memory allocation using malloc
int **arrM = (int**)malloc (row*sizeof(int*));
for (int i=0;i<row;i++)
{
arrM[i] = (int*)malloc(column*sizeof(int));
// insert the value for each field
for (int j =0;j<column;j++,val++)
{
arrM[i][j] = val;
}
}
// De-allocation
for (int i=0;i<row;i++)
{
free(arrM[i]);
}
free(arrM);
arrM = 0;
//
// Now using New operator:
//
int **arr = new int*[row];
int k = 1;
for (int i=0;i<row;i++)
{
arr[i] = new int[column];
// insert the value for each field
for (int j =0;j<column;j++,k++)
{
arr[i][j] = k;
}
}
cout<<"array value is = "<<*(*(arr+0)+0)<<endl;
cout<<"array value is = "<<*(*(arr+3)+2)<<endl;
// Need to deallcate memory;
for (int i=0;i<row;i++)
{
delete [] arr[i];
}
delete []arr;
arr = 0;

Resources