Accessing dynamic memory in a struct pointer - c

I'm writing some code to interact with dynamic memory that i' creating and i want to know why it's not working.
struct order{
char *bookTitle;
double price;
char *category;
double remain;
int custID;
char processed;
};
typedef struct order order;
struct orderNode{
order *order;
struct orderNode *next;
};
typedef struct orderNode orderNode;
Here is the code creatinng an array or orderNodes and trying to access them. The print statement is giving me a segmentation fault. Not sure why.
orderNode **processQueue = malloc(sizeof(orderNode)*numcats) ;
//sort the orders into their respective categories
//sortOrders(processQueue, unSortedQueue, numcats);
processQueue[1]->order->category = "herro" ;
puts("string set. \n");
printf("%s\n",processQueue[1]->order->category);
/*
gdb backtrace output.
#0 strlen () at ../sysdeps/x86_64/strlen.S:106
#1 0x00007ffff786794c in _IO_puts (str=0x1000000000a2074 <error: Cannot access memory at address 0x1000000000a2074>)
at ioputs.c:36
#2 0x000000000040192f in main (argc=4, argv=0x7fffffffdbd8) at main.c:444
*/
Thanks in advance!

I think that instead of
orderNode **processQueue = malloc(sizeof(orderNode)*numcats) ;
you mean
orderNode *processQueue = malloc(sizeof(orderNode)*numcats) ;
Also take into account that for each orderNode in the array you have to allocate data member order before trying to access its own data members.
And indices in C start from zero. It seems that in this statement
processQueue[1]->order->category = "herro" ;
you want to access processQueue[0] instead of processQueue[1]
The code could look like
orderNode *processQueue = malloc( sizeof( orderNode ) * numcats );
processQueue[0].order = malloc( sizeof( order ) );
processQueue[0].order->category = "herro";
puts( "string set." );
puts( processQueue[0].order->category );

You never allocated any of your order:
orderNode *processQueue = calloc(numcats, sizeof(orderNode)) ;
for (i=0;i<numcats;i++)
processQueue[i].order = calloc(1, sizeof(order));
Also, I used calloc for the first allocation to make sure all of your next pointers are NULL. I'm not sure what you plan on doing with those next pointers, though.
EDIT: also, as Vlad from Moscow pointed out, processQueue was of the wrong type (I fixed the type above).

Related

Pointing to an array inside a struct that is inside another struct

How can I access an array / other type of data that is inside of a struct which is inside of another struct. This is what Ive tried so far and its coming out as c is not declared. I know I can declare c as prod_t *c but it defeats the purpose of something Im trying to do as it doesnt exist inside of the root(a_t struc).
typedef struct {
char *name;
} prod_t;
typedef struct {
prod_t *c;
} a_t;
int
main(int agrc, char **argv){
a_t *root = malloc(sizeof(a_t));
root->c=malloc(sizeof(prod_t));
c->name = malloc( 5 * sizeof(char));
strcpy(c->name, "abc");
printf("%s",root.c->name);
return 0;
}
In your code, c->name is not a valid variable name. c is a member variable of the structure variable root. There is no standalone variable named c.
You can use like
root->c->name = malloc( 5 );
and
strcpy(root->c->name, "abc");
and
printf("%s\n", root->c->name);
Also, remember,
sizeof(char) is guranteed to produce 1 in C, so you can drop that part.
Once you're done using the allocated memory, you need to free() them.
You have three pointers one is "enclosed" in another. So you have to write
root->c->name = malloc( 5 * sizeof(char));
strcpy( root->c->name, "abc");
printf("%s",root->c->name);
And you have to free them in the following order
free( root->c->name );
free( root->c );
free( root );
Take into account that in general you have to check whether the "outer" pointer was successfully "allocated" before allocating memory pointed to by the "inner" pointer.

display a specified index of a pointer char*

I am trying to point on a specified character in a string contained on a structure
here my code
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = (person)malloc(sizeof(PERSON));
strcpy(&(serenity->name),"Serenity");
printf("%c",*(&(serenity->name)+1));
}
here i wanted to display the second character which is 'e' but it shows 'n' instead
anyone can explain me what is wrong with this,
thank you
You have not allocated memory for name
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = malloc(sizeof(PERSON));
serenity->name = malloc(sizeof("Serenity")); //<< Missing
strcpy((serenity->name),"Serenity");
printf("%c",*((serenity->name)+1)); // << Also you want the value in pointer name NOT its address
return 0;
}
Outputs e. Also since you tagged C there is no need to cast the return type of malloc.
Okay, okay... All of those answers aside, if you do not aim to change the characters inside the string "Serenity" in the future, you could just do the following:
#include <stdio.h>
typedef struct{
const char *name; // <-- added const
int age;
}PERSON, *person;
int main( ){
person serenity;
serenity = (person) malloc( sizeof( PERSON ) );
serenity->name = "Serenity"; // <-- simply assigned the pointer with the
// address to the array of constant characters
printf( "%c", *( serenity->name + 1 ) ); // <-- changed this
}
This statement
serenity = (person)malloc(sizeof(PERSON));
allocates the structure
typedef struct{
char *name;
int age;
}PERSON
however name is kept uninitialized and points somewhere in memory causing a crash when you copy to it.
So instead of
strcpy(&(serenity->name),"Serenity");
write
serenity->name = strdup("Serenity");
which is the same as
serenity->name = malloc(strlen("Serenity")+1);
strcpy(serenity->name,"Serenity");
don't forget to free that string as well later.
Try printf("%c",*(serenity->name+1));, also do strcpy(serenity->name,"Serenity");.
If you have a pointer char* name; you access the second element by doing name[1] or *(name+1). &name will give you the address where the pointer address of name is stored. This is not what you want here.
Another issue in your program is that you never allocate memory for the variable name. You need a serenity->name = (char*)malloc(128);. But using an arbitrary length like 128 is very dangerous in combination with strcpy. Use strncpy instead of strcpy to work around this.

Why does accessing a member of a malloced array of structs seg fault?

I am working through Learn C The Hard Way and am stumped on something. I've written a simplified version of the problem I am running into to make it easier to get down to it:
#include <stdlib.h>
#define GROUP_SIZE 10
#define DATA_SIZE 64
struct Dummy {
char *name;
};
struct Group {
struct Dummy **dummies;
};
int main() {
struct Group *group1 = malloc(sizeof(struct Group));
group1->dummies = malloc(sizeof(struct Dummy) * GROUP_SIZE);
struct Dummy *dummy1 = group1->dummies[3];
// Why does this seg fault?
dummy1->name = (char *) malloc(DATA_SIZE);
return 0;
}
When I try to set the name pointer on one of my dummies I get a seg fault. Using valgrind it tells me this is uninitialized space. Why is this?
Your use of dummies appears inconsistent with its declaration. From the way you use the dummies field it appears that dummies was intended as an array of Dummy structs, not an array of arrays of Dummy structs. If this is the case, change your declaration to this:
struct Group {
struct Dummy *dummies; // Single asterisk
};
Then change your usage as follows:
struct Dummy *dummy1 = &group1->dummies[3];
Of course this assumes that GROUP_SIZE is four or more.
you never malloced space for the Dummy itself. You need to do something like:
group1->dummies = malloc(sizeof(Dummy *) * GROUP_SIZE);
for(int i = 0; i < GROUP_SIZE; i++) {
group1->dummies[i] = malloc(sizeof(struct Dummy));
}

How to access union inside structure?

I have the following code:
/* sample.c */
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include"hermes.h"
#include<string.h>
int main (){
struct hermes *h ;
h = ( struct hermes *) malloc ( sizeof ( struct hermes *));
strcpy ( h->api->search_response->result_code , "123" );
printf("VALue : %s\n" , h->api->search_response->result_code );
return 0;
}
/* hermes.h */
struct hermes {
union {
/* search response */
struct {
int error_code;
char *result_code;
char *user_track_id;
struct bus_details bd;
}*search_response;
}*api;
};
I get a segmentation fault when I try to access the elements. Could anyone tell me what is the right way to access these elements?
Your malloc() line isn't correct:
h = ( struct hermes *) malloc ( sizeof ( struct hermes *));
should be:
h = ( struct hermes *) malloc ( sizeof ( struct hermes));
Remove the * in the sizeof(). Otherwise, you're only allocating enough for a pointer rather than the struct itself.
Also, the cast isn't necessary in C.
Use this struct:
#define MAX 512 /* any number you want*/
struct hermes {
union {
/* search response */
struct {
int error_code;
char result_code[MAX];
char user_track_id[MAX];/* can use different sizes too*/
struct bus_details bd;
}search_response[MAX];/* can use different sizes too*/
}*api;
};
Or if you want to use your current struct, malloc the pointer element like:
h->api = malloc((sizeof(int)+sizeof(char)*MAX*2+sizeof(struct bus_details))*MAX)
It's not a problem of accessing the elements. That's about all that you are doing correctly.
Here are some of the things that are wrong. First, you aren't allocating enough space for a hermes struct, just enough for a pointer. Then, even if you malloc( sizeof ( struct hermes ) );, the one element (api) is an uninitialized pointer. You can't just follow uninitialized pointers down deep into the data structure, because they will be pointing to who knows where in memory. You first need to allocate something for h->api to point to. Then you need to allocate space for h->api->search_response. If you correct all that, then you are copying a string to ... who knows where? You should use strdup, not strcpy to create a new string, then you should assign the return value to result_code. Also, your union has only one element, so it's kind of pointless (unless there's more to it that you haven't posted).
EDIT Here's one way of initializing h:
h = malloc( sizeof( struct hermes ) );
h->api = malloc( sizeof( *h->api ) );
h->api->search_response = malloc( sizeof( h->api->search_response ) );
h->api->search_response->result_code = strdup( "123" );
Note that in a well-behaved program that cleans up after itself, each of these allocations will have to be freed individually as well, in reverse order of the calls to malloc. Since you immediately call exit(0), no harm is done in this case if you don't.

C Structs: Problem Initializing? Valgrind Errors

Coding in C:
typedef struct {
char *string;
int one;
int two;
} Example;
... elsewhere:
Example *new = (Example *)malloc(sizeof(Example*));
new->string = strdup(otherstring); //no problem here
new->one = 5; //valgrind says that there is an invalid write of size 4.
My program runs fine, I just can't make valgrind happy. And that probably means I will have some other error elsewhere.
I guess I don't have to declare a pointer to the structure, (i.e., I could call "Example new" instead), but I'm stuck finding out how to allocate memory on the heap because I will need to access "new" from other parts of the program.
Am I making a mistake in the above few lines? Or is my error likely to be somewhere else? This is the first memory error that valgrind reports.
EDIT: accidentally had int *s instead of ints in my struct. Fixed.
I see various problems here. First of all, this:
Example *new = (Example *)malloc(sizeof(Example*));
doesn't allocate the right amount of memory (and you don't need the cast). You want this:
Example *new = malloc(sizeof(Example));
Then, you say this:
new->one = 5;
and that's assigning an int to an int*; that's not a good idea and valgrind rightly complains about it. If your struct is properly declared, then you want this:
new->one = malloc(sizeof(int)); /* The other malloc doesn't allocate this, you have to. */
*(new->one) = 5;
I suspect (as you say that everything works) that you really mean to declare your struct like this:
typedef struct {
char *string;
int one;
int *two;
} Example;
but there isn't enough information to be certain. Then you probably still have similar issues with new->two.
Example *new = (Example )malloc(sizeof(Example));
Should be:
Example *new = (Example *)malloc(sizeof(Example);
You have to allocate the whole struct not just a reference to it. Sometimes the program runs just because you get lucky.
Try this instead (just cut, paste, and run):
Example *new = (Example *)malloc(sizeof(Example)); //This is the correct method as pointed out by Bob, otherwise you're allocating only enough space to fit a memory location vs the struct
new->string = strdup(otherstring); //this is okay
new->one = (int*)malloc(sizeof(int));
*(new->one) = 5; //You want to assign the value 5 to the new->one memory location, not assign new->one pointer the value of 5!!!

Resources