Accessing dynamically allocated structure inside a function - c

In the below code, I want to access the structure element that is dynamically allocated inside a function. I have declared structure globally, but allocated inside fun1(). I cannot access the structure element after receiving the structure elements. Kindly help me where I have gone wrong. This works fine if it is in single function. Thanks in advance.
struct s1
{
int a;
char b[10];
} *s2;
int val;
void main()
{
fun1();
fun2();
printf("\n Element a %d",(s1->a));
}
fun1()
{
struct s1 *s2=malloc(sizefof(struct s1)*val);
recv(fd,(void)&s2,sizeof(struct s1),0);
}
fun2()
{
printf("\n Element a %d",(s1->a));
}

There's a lot of confusion here.
Something like this might be what you're after:
struct s1
{
int a;
char b[10];
};
struct s1 * fun1(int val)
{
struct s1 *s = malloc(val * sizeof *s);
if(s != NULL)
recv(fd, s, val * sizeof *s, 0);
return s;
}
void fun2(struct s1 *ptr)
{
printf("First element's a %d", ptr[0].a);
}
int main(void)
{
struct s1 *data = fun1(100);
fun2(data);
printf("First element's a is %d", data[0].a);
return 0;
}
Note that recv() can fail too, and that should be checked. It should, also, perhaps be a read()?
Basically I removed the global variables, and fixed basic errors in allocation and pointer usage.

You have a couple of problems I can see, assuming that int val; was initialized and it's value is reasonable
You don't check for the return value of malloc, it's very unlikely that this is the problem, but that also depends on the value of val.
You pass the address of the pointer to recv.
fun2() makes no sense at all, the code shouldn't even compile.
You redeclare s2 in fun1(), which doesn't seem to be what you want, since you have initially declared s2 global.
The printf() statement in main() is also broken.
Note: in 4 and 5, you should notice that s1 is the name of the struct, which was a very bad choice and pretty much the first source for your confusion.
So fun1() should be re-wirtten
fun1()
{
s2 = malloc(sizefof(*s1) * val);
if (s2 != NULL)
recv(fd, s2, val * sizeof(*s2), 0);
}
and fun2()
fun1()
{
if (s2 != NULL)
printf("\n Element a %d", s2->a);
}

Related

Malloc within function not changing pointer value

So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}

Why strcpy doesn't work but direct assign works?

In the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char** tab;
int n;
}slist;
void print(slist* p);
void add(slist* p, const char* s);
void add(slist* p, const char* s)
{
if(p->n==0)
{
p->tab=(char**)malloc(sizeof(char**));
}
strcpy(p->tab[p->n],s);
p->n=p->n+1;
}
void print(slist* p)
{
int i;
printf("[");
for(i=0;i<p->n;i++)
printf(" %s",p->tab[i]);
printf(" ]");
}
int main()
{
char s1[25] = "Picsou";
char s2[25] = "Flairsou";
slist* p = (slist*)malloc(sizeof(slist));
p->n=0;
p->tab=NULL;
add(p,s1);
add(p,s2);
print(p);
return 0;
}
the function add() doesn't work, but if I change it to:
void add(slist* p, const char* s)
{
if(p->n==0)
{
p->tab=(char**)malloc(sizeof(char**));
}
p->tab[p->n]=s;
p->n=p->n+1;
}
it seems to work perfectly well. In the first case the output is only " [";
in the second case it is what is should be: " [ Picsou Flairsou ] ".
I cannot understand why.
I also tried this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char** tab;
int n;
}slist;
void print(slist* p);
void add(slist* p, const char* s);
void print(slist* p)
{
int i;
printf("[");
for(i=0;i<p->n;i++)
printf(" %s",p->tab[i]);
printf(" ]");
}
void add(slist* p, const char* s)
{
slist* tmp = (slist*)malloc(sizeof(slist));
tmp->tab=(char**)malloc(sizeof(char*)*(p->n+1));
int i;
for(i=0;i<p->n;i++)
tmp->tab[i]=(char*)malloc(sizeof(char));
strcpy(tmp->tab[p->n],s);
tmp->n=p->n+1;
p = tmp;
}
int main()
{
char* s1 = "Picsou";
char* s2 = "Flairsou";
slist* p = (slist*)malloc(sizeof(slist));
p->n=0;
p->tab=NULL;
add(p,s1);
add(p,s2);
print(p);
return 0;
}
Lots of errors here, which is common with people who are new to dealing with pointers. Where to begin... I'll just go in the order things appear in code.
This is not a "list".
It's an array... sort of. If you say "list" to a C programmer, they will think you mean a linked-list.
Incorrect allocation of array.
if(p->n==0)
{
p->tab=(char**)malloc(sizeof(char**));
}
Here you have allocated enough to store a single pointer. The second time you call add, you're going to access memory off the end. You have also incorrectly cast the result (in C, you don't cast the return value from malloc). Additionally, you have given confusing information to the reader, because you intend to allocate an array that will hold elements of type char*, NOT char**.
You must either allow the array to expand dynamically when required (not appropriate for your abilities right now - maybe try that in a few days), or set a maximum size. Let's do that.
const int MAX_SIZE = 100;
if( p->n==0 )
{
p->tab = malloc( MAX_SIZE * sizeof(char*) );
}
else if( p->n == MAX_SIZE )
{
printf( "Maximum size exceeded!\n" );
return;
}
You could use calloc instead of malloc if you like. It will zero-initialise the block after allocating it: calloc( MAX_SIZE, sizeof(char*) )
Copying to an uninitialized pointer.
strcpy(p->tab[p->n],s);
You allocated memory for tab, but you did not allocate memory that is pointed to by its elements, and here you have undefined behaviour (most likely resulting in a segmentation fault, but could do anything).
Make sure you have a valid pointer, and the location it points has enough storage reserved for the data you are copying into it:
p->tab[p->n] = malloc( strlen(s) + 1 );
strcpy( p->tab[p->n], s );
Storing potentially invalid pointer.
Your alternative that "works perfectly well" uses:
p->tab[p->n]=s;
However, the only reason this works is because those pointers remain valid for the whole time that you use the "list" (but actually the program does not "work" because of reasons I highlighted in number 2.
Sometimes we desire this behaviour in a program, and design our data structures to index pointers that they do not own. But more often, and especially for a beginner, you are better off copying the data (instead of simply copying the pointer). And so you'll instead use the approach I've suggested in number 3 above.
No comment!!
There are so many things wrong with the following code, that I'm not going to pull it apart or explain them.
void add(slist* p, const char* s)
{
slist* tmp = (slist*)malloc(sizeof(slist));
tmp->tab=(char**)malloc(sizeof(char*)*(p->n+1));
int i;
for(i=0;i<p->n;i++)
tmp->tab[i]=(char*)malloc(sizeof(char));
strcpy(tmp->tab[p->n],s);
tmp->n=p->n+1;
p = tmp;
}
However, it appears like you were attempting to do something similar to realloc. This is the option I mentioned in number 2 that I said you're maybe not ready for. But read up on it anyway: realloc

Storing void pointers in a struct

I'm getting segmentation fault on code that is trying to initialize a struct of pointers to 0mq context and socket. The commented out code in the main method works, but it's only using local variables. I would like to initialize them and pass them around in a struct, but my google foo is failing me on how to do this properly.
#include "zhelpers.h"
#include <stdio.h>
#include <stdlib.h>
#include <zmq.h>
struct publisher{
void *handle;
void *context;
};
void init_publisher(struct publisher *p);
void destroy_publisher(struct publisher *p);
void publish(struct publisher *p,char *msg);
void init_publisher(struct publisher *p)
{
p = (struct publisher *)malloc(sizeof(struct publisher));
p->context = malloc(sizeof(void *));
p->handle = malloc(sizeof(void *));
void *context = zmq_ctx_new();
void *handle = zmq_socket(context,ZMQ_PUB);
zmq_bind(handle, "tcp://*:5556");
zmq_bind(handle, "ipc://feed.ipc");
p->context = context;
p->handle = handle;
}
void destroy_publisher(struct publisher *p)
{
zmq_close(p->handle);
zmq_ctx_destroy(p->context);
free(p->handle);
free(p->context);
free(p);
}
void publish(struct publisher *p,char *msg)
{
s_send(p->handle, msg);
}
int main(void)
{
/**
void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
int rc = zmq_bind(publisher, "tcp://*:5556");
assert(rc == 0);
rc = zmq_bind(publisher, "ipc://weather.ipc");
assert(rc == 0);
printf("Started Weather Server...\n");
srandom((unsigned) time (NULL));
int zipcode, temperature, relhumidity;
zipcode = randof(100000);
temperature = randof (215) - 80;
relhumidity = randof (50) + 10;
char update[20];
sprintf(update, "%05d %d %d", zipcode, temperature, relhumidity);
s_send(publisher, update);
zmq_close(publisher);
zmq_ctx_destroy(context);
*/
struct publisher *p;
init_publisher(p);
printf("Setup pub\n");
srandom((unsigned) time (NULL));
int zipcode, temperature, relhumidity;
zipcode = randof(100000);
temperature = randof (215) - 80;
relhumidity = randof (50) + 10;
char update[20];
sprintf(update, "%05d %d %d", zipcode, temperature, relhumidity);
publish(p,update);
printf("Published Message\n");
destroy_publisher(p);
printf("Destroyed publisher\n");
return 0;
}
There appears to be nothing in this code that would make it crash. (Assuming you know how all your zmq_... stuff works.)
It would have helped if you told us precisely where the error occurs, but my guess would be that the error occurs outside of this code.
You see, you are passing struct publisher *p to your init_publisher() function, but then you are allocating memory for p inside that method, (which makes passing p pointless,) and then you are not returning p. As a result, the code that calls init_publisher() probably expects p to be initialized, but it is not. The memory pointed by p is just allocated and leaked locally within your init_publisher() function.
So, instead of passing p, just have the function declare it and return it.
Alternatively, if the caller has already allocated p, then do not allocate it all over again from within init_publisher().
Please also note that the statements p->context = malloc(sizeof(void *)); are unnecessary and they are leaking small amounts of memory, because you proceed to overwrite these struct members.
The problem is that the passed pointer and the pointer you malloc()ed are not the same. The passed pointer contains the same address of your original pointer, presumably an invalid address, but the addresses of the poninters them selves are different because in c you can only pass a variable by value and hence, the pointer is copied.
That means that when you reassign p inside the function, the p from outside the function is unaltered. It would be different if it was allocated outside and you just use the function to access it's members.
You also don't need to malloc() every pointer you want to use, the thing is that it must point to a valid address before dereferencing it. When you want to request new uninitialized memory then you use malloc() otherwise you just make the pointer point to a valid address so that dereferencing it is defined, one example of using a pointer without malloc()ing it is
int *pointer;
int value;
value = 4;
pointer = &value; // Now `pointer' points to `value's` address
*pointer = 3;
printf("%d\n", value);
One way to write the function would be
int
init_publisher(struct publisher **pp)
{
struct publisher *p;
*pp = malloc(sizeof(struct publisher));
if (*pp == NULL)
return -1;
p = *pp;
p->context = zmq_ctx_new();
p->handle = zmq_socket(context,ZMQ_PUB);
if (p->handle != NULL) /* Just in case, do not dereference a NULL pointer */
{
zmq_bind(p->handle, "tcp://*:5556");
zmq_bind(p->handle, "ipc://feed.ipc");
}
return 0;
}
and then you could use it like this
struct publisher *p;
if (init_publisher(&p) != 0)
do_something_there_was_an_error();
/* Continue using `p' */
Note that the funcion is returning a value indicating whether allocations succeeded or not. Normally malloc() will not fail, but that doesn't mean that you should ignore the possible failure.
What I mean when I say if you allocate p first, is that if you instead do this
struct publisher *p;
p = malloc(sizeof(*p));
if (p == NULL)
return handle_error();
init_publisher(p);
then init_publisher() could be
void
init_publisher(struct publisher *pp)
{
void *context;
void *handle;
p->context = zmq_ctx_new();
p->handle = zmq_socket(context,ZMQ_PUB);
if (p->handle != NULL) /* Just in case, do not dereference a NULL pointer */
{
zmq_bind(p->handle, "tcp://*:5556");
zmq_bind(p->handle, "ipc://feed.ipc");
}
}
which is probably what you was trying to do.

Significance of double pointer and triple pointer in this code snippet

#include<stdio.h>
#include<stdlib.h>
void add(char **p);
void print(char **p);
int cnt=0;
main()
{
int option;
char **p=NULL;
while(1)
{
printf("------MENU-----\n");
printf("1>input\n 2>print\n3>exit\n");
printf("enter ur choice\n");
scanf("%d",&option);getchar();
switch(option)
{
case 1: add(p);
break;
case 2: print(p);
break;
case 3: return;
default: printf("Invalid option\n");
}
}
}
void add(char **p)
{
int i;
p=(char**)realloc(p,(cnt+1)*sizeof(char*));
if(p==NULL)
{
printf("Error: memory not available\n");
return;
}
p[cnt]=NULL;
p[cnt]=(char*)realloc(p[cnt],20*sizeof(char));
puts("enter a name");
gets(p[cnt]);
cnt++;
printf("cnt=%d\n",cnt);
}
void print(char **p)
{
int i;
for(i=0;i<cnt;i++)
printf("p[%d]=%s\n",i,p[i]);
}
In the above code, I am making a database of names. For this I am using dynamic memory allocation. I am allocation memory for 2D-array using array of pointers method. When I am executing this program on gcc compiler, I am getting segmentation fault. I am not understanding why is it happening?Could you please tell me where the bug is?
In main, all you do is to assign p = NULL and then use this NULL pointer in print, which causes the segfault. Note that add(p) is equivalent to add(NULL) and does not change p.
Did you mean to pass an address with add(&p)? If so, you need to fiddle a bit with the number of *.
p in main is handed over to add by value. add modifies a local copy then, but not the original p.
Besides the terrible formatting and everything you need to hand a pointer to your main's p to add:
...
case 1: add(&p);
...
void add(char ***p)
{
int i;
*p = realloc(*p,(cnt+1)*sizeof(char*));
if(*p==NULL)
{
printf("Error: memory not available\n");
return;
}
(*p)[cnt]=NULL;
(*p)[cnt]=realloc((*p)[cnt],20*sizeof(char));
puts("enter a name");
gets((*p)[cnt]);
cnt++;
printf("cnt=%d\n",cnt);
}
A copy of 2D pointer p is created in the add function, and updating this pointer will not be reflected in the main function.
A quick solution to this problem is to return the 2D pointer 'p' from the add function.
char** print(char **p)
{
....
....
return p;
}
Pass by reference. You need to pass the address of your pointer to make sure the changes in function add() is reflected in main(). Avoid using gets()
In this case
add(&p);
Accordingly your add() function definition should change to handle this.
Or the other way is for the add function to make the required allocations and return that address to your pointer
char **add();
Check the code below:
char **add(char **p)
{
int i;
p=(char**)realloc(p,(cnt+1)*sizeof(char*));
if(p==NULL)
{
printf("Error: memory not available\n");
return;
}
p[cnt]=NULL;
p[cnt]=(char*)realloc(p[cnt],20*sizeof(char));
scanf("%s",p[cnt]);
cnt++;
printf("cnt=%d\n",cnt);
return p;
}
So your call should be:
p = add(p);
Apart from the other things, I don't think anyone's mentioned the realloc trap of reallocation failure. Suppose this call
p=(char**)realloc(p,(cnt+1)*sizeof(char*));
fails to allocate the new memory: what happens then? Yes, you will get NULL returned: but the memory which was allocated, and which pis pointing to, does not get free'd. Instant memory leak.
You must call realloc like this:
char* pTemp = realloc(p, cnt + 1);
if(pTemp != NULL)
{
p = pTemp; // Now safe to update p
}
else
{
// Error handling as required, possibly including freeing p
}
Yet another reason not to use realloc. It doesn't really by you very much over doing the buffer copies yourself IMHO.

How to walk through array of Struct in c

I have a program which creates an array or struct and go through it for processing. Initially it initialize the array with the defined nyumber of elements. Then for some number of element in array, the name is assigned.
I pretend the code that is equal to my scenario which is tested in codebloc and get the similar error. The problem is described in comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _car {
char *name;
int year;
} Car;
char *getCarName(char *name, int var);
void processCar();
void printCars(Car car[]);
int INCREMENT = 10;
int main(void)
{
processCar();
return 0;
}
void processCar()
{
// create car array with amount of INCREMENT
Car CAR_ARRAY[INCREMENT];
int a=0;
// This function assign name for Car amount 10 less than INCREMENT
while (a<INCREMENT - 2) {
char *carName;
carName = getCarName(&carName, a);
CAR_ARRAY[a].name = malloc(strlen(carName) + 1);
strcpy(CAR_ARRAY[a].name, carName);
a++;
}
printCars(CAR_ARRAY);
}
void printCars(Car car[])
{
printf("IN Car \n");
int a = 0;
// when try to call name for car amount equals to INCREMENT program terminates.
while(a<INCREMENT) {
if (car[a].name != NULL) // checking if NULL
printf("Car Name : %d -> %s\n", a, car[a].name);
a++;
}
}
char *getCarName(char *name, int var)
{
name = "Toyota";
return name;
}
What is the right way to check the struct value on struct array whether it can be called?
EDIT
I created a hack to do this as follows.
// added these right after creating array
for (a = 0; a < INCREMENT; a++)
CAR_ARRAY[a].name = NULL;
I dont know if it is a standard way or not. pls advice.
You are checking for NULL before printing, which is a good idea, but it doesn't help you here, because your last two cars are uninitialised and likely contain garbage: The name pointer is not NULL, but doesn't point to a valid address either. Segmentation violation ensues.
You should initialise all cars, not only INCREMENT - 2. Alternatively, you could initialise your cars to zero by calling memset before your initialisation:
memset(CAR_ARRAY, 0, sizeof(Car) * INCREMENT);
As an aside, the way you deal with getCarName is rather shaky as well. At the moment, your name is a pointer to a string literal. Your local variable carName does a half-hearted double duty: You try to pass it by reference (but essentially you don't) and you also return it.
Basically, you could do this in one of two ways. The easier one here is to return a pointer. in that case, you don't have to pass any string:
char *getCarName(int var)
{
static char *names[3] = {"Toyota", "Dodge", "Peugeot"};
return names[var % 3];
}
and call it like so:
char *carName = getCarName(&carName, a);
Alternatively, you could pass a char pointer by reference, i.e. as pointer to pointer to char. In that case, you don't have to return anything:
void getCarName(char **name, int var)
{
static char* names[3] = {"Toyota", "Dodge", "Peugeot"};
*name = names[var % 3];
}
Call it like so:
char *carName;
getCarName(&carName, a);
There are other scenarios here, for example if you just pass a char pointer and have getCarName fill it, but I'll leave that for now - it would make everything even more complicated.

Resources