I am trying to allocate individual elements of two dimensional array in function call.
I am getting the pointer reference char ***a
pointer in function parameter like this int substr(char *arr,char c,char ***a,int k)
But I am getting segFault at realloc line. I am not getting any help from -Wall -Wextra. In this example the function substr allocate for 1 index element of two passed two dimensional array
But I like to allocate memory in called function
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int substr(char *arr, char c, char ***a, int k)
{
*(a k) = realloc(a, 5);
return 0;
}
int main()
{
char *arr = "this is a new string. check it out";
char **a;
a[0] = malloc(5);
//....some code
//...
int count = substr(arr, ' ', &a, 1);
return 0;
}
CodePudding user response:
From the conversation in the comments, there's some confusion about a[0]
. Let's simplify it by working with char *
.
// Declare the variable a which stores a pointer to a char.
char *a;
// Same as *a = 'b'
a[0] = 'b';
a[0]
tries to access the memory a
points to, same as *a
. But a
was never initialized, it points at some random memory you don't have access to, or is out of bounds. Segfault.
a
has to have memory allocated to it to store 'b'.
// `a` points at 5 bytes of memory
// This is the same as `char *a; a = malloc(5)`.
char *a = malloc(5);
// The first byte of malloc'd memory is set to 'b'.
a[0] = 'b';
Now let's do it with an array of strings.
char **a;
a[0] = "some string";
Same problem. a
is uninitialized and points at some random memory. a[0] = "some string";
tries to dereference a
and segfaults.
So we need to first allocate space to store the pointers to the strings.
// Allocate space for 5 pointers.
// This is the same as `char **a; `a = malloc(...);`
char **a = malloc(sizeof(char *) * 5);
// Dereference the first pointer and have it point to a string.
a[0] = "some string";
Now to your code. Same thing.
char **a = malloc(sizeof(char *) * 5);
// Derefrence the first pointer in a and have it point to 5 bytes of memory.
a[0] = malloc(5);
If you want to reallocate the memory in a[0]
you reallocate a[0]
, not a
.
// Reallocate the 5 bytes of a[0] and return a pointer to 10 bytes.
// Assign the new pointer to a[0].
a[0] = realloc(a[0], 10);
If you want to do this in a function, pass in a pointer to the memory work with that. The function doesn't know nor care about the array a
. Just the string.
// Note there's no need to pass in an array index.
void substr(char **dest) {
// dest is pointer to the pointer in a[0].
// *dest is the pointer in a[0], the malloc(5).
// Grow its memory and reassign it back to a[0].
*dest = realloc(*dest, 10);
// Assign to a[0] to demonstrate it works.
strcpy(*dest, "012345678");
}
int main(void) {
char **a = malloc(sizeof(char *) * 5);
a[0] = malloc(5);
substr(&a[0]);
puts(a[0]);
}
We can simplify this.
First, since a
is allocated in main it can use automatic memory. This is memory which is automatically deallocated when the function exits. Because main
is the first function it will be the last to exit, so any automatic memory in main
will last for the whole program.
We can't use automatic memory in substr
because it will be deallocated when substr
returns.
Second, there's no need to allocate memory to a[0]
if you're going to immediately realloc
it. If you give realloc
a null pointer it will allocate new memory.
int main(void) {
char *a[5];
a[0] = NULL;
substr(&a[0]);
puts(a[0]);
}
Finally, we can initialize all the pointers of a
to NULL using a little syntactic trick.
int main(void) {
// Same as char *a[5] = {NULL, NULL, NULL, NULL, NULL};
char *a[5] = {NULL};
substr(&a[0]);
puts(a[0]);
}