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.
Related
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.
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).
I am learning C and have a question about structs.
I have a
struct myStruct {
char member1[16];
char member2[10];
char member3[4];
};
This should take at least 30 bytes of memory to store. Would it be possible to copy all of this data into the variable char foo[30]? What would be the syntax?
You can't just directly copy the whole thing, because the compiler may arbitrarily decide how to pad/pack this structure. You'll need three memcpy calls:
struct myStruct s;
// initialize s
memcpy(foo, s.member1, sizeof s.member1);
memcpy(foo + sizeof s.member1, s.member2, sizeof s.member2);
memcpy(foo + sizeof s.member1 + sizeof s.member2, s.member3, sizeof s.member3);
The size of struct myStruct is sizeof(struct myStruct) and nothing else. It'll be at least 30, but it could be any larger value.
You can do this:
char foo[sizeof(struct myStruct)];
struct myStruct x; /* populate */
memcpy(foo, &x, sizeof x);
According to the C Standard (6.2.6 Representations of types)
4 Values stored in non-bit-field objects of any other object type
consist of n × CHAR_BIT bits, where n is the size of an object of that
type, in bytes. The value may be copied into an object of type
unsigned char [n] (e.g., by memcpy); the resulting set of bytes is
called the object representation of the value.
So you can write simply
unsigned char foo[sizeof( struct myStruct )];
struct myStruct s = { /*...*/ };
memcpy( foo, &s, sizeof( struct myStruct ) );
Take into account that you could copy the data members separatly in one array. For example
unsigned char foo[30];
struct myStruct s = { /*...*/ };
unsigned char *p = foo;
memcpy( p, s.member1, sizeof( s.member1 ) );
memcpy( p += sizeof( s.member1 ), s.member2, sizeof( s.member2 ) );
memcpy( p += sizeof( s.member2 ), s.member3, sizeof( s.member3 ) );
Yes, it is possible.
There are different ways you can go about doing this. Below are the two simplest methods.
struct myStruct myVar;
/* Initialize myVar */
...
memcpy (foo, &myVar, sizeof (myStruct));
Or if you are dealing with a pointer ...
struct myStruct * myVarPtr;
/* Initialize myVarPtr */
...
memcpy (foo, myVarPtr, sizeof (myStruct));
Note that when copying a structure to/from a character array like this, you have to be very careful as structure sizes are not always what you might first think. In your particular case, there might not be any issues; but in general, you should at least be aware of potential padding, alignment and type size issues that may change the size of your structure.
Hope this helps.
you could do the following if you have a myStruct variable named st:
strcpy(foo, st.member1);
strcat(foo, st.member2);
strcat(foo, st.member3);
Pretty simple with memcpy.
char foo[30];
struct myStruct s;
s.member1 = //some data
s.member2 = //some data
s.member3 = //some data
memcpy(foo, &s, 30);
I am using ANSI C code, generated from a code generator that produces several layers of nested struct as well as function prototypes with argument lists that use pointers to the top layer struct for passing or accessing data located in the inner mmost struct.
Because the function prototypes pass pointers to struct, the application must allocate memory to access or write data to the inner most struct members. I am seeing the problem when attempting to allocate memory for the pointer to the second nested struct.
The actual error message I get is a non-fatal, run-time:
"Not enough space for casting expression to 'pointer to struct data'."
I am not explicitly casting anything, so I suspect the implementation of malloc() may have an assert that generates the message when it sees some condition. The wording of this error may be specific to my environment (I am using LabWindows/CVI) but I would be interested in hearing of results of other ANSI C compilers as well.
Here is a simplified, complete, code snippet that should compile, build and run (up to the error location, which is commented in-line)
I would appreciate comments on the cause of my error, and suggestions on how to fix it.
#include <ansi_c.h> //specific to LabWindows/CVI - change as needed for your environment
struct request
{
struct data *pData;
};
struct data
{
char *wsDate;
char *wsDuration;
char *wsFailures;
int __sizeM_Details;
struct details *M_Details;
};
struct details
{
char *wsStep;
char *wsTestDesc;
char *wsLowLim;
};
typedef struct request REQUEST; // from mtdf function prototype request argument (4)
typedef struct details DETAILS; // member of REQUEST - _ns1__MTDFData_MTDFDetail
void allocate(REQUEST *a, int numRecords);
void freemem(REQUEST *c, int numRecords);
int main(void)
{
REQUEST b, *pB;
pB = &b;
allocate(pB, 10);
freemem(pB, 10);
return 0;
}
void allocate(REQUEST *c, int numRecords)
{
DETAILS m_Param;
REQUEST b;
struct data d;
size_t size_c = sizeof(c);
c = malloc(size_c); //4 bytes
size_t size_c_data = sizeof(c->pData);
c->pData = malloc(size_c_data); //Breaks here - this is just a pointer,
//should it not just allocate 4 bytes
//and continue?
// Actual error message:
// "Not enough space for casting expression to 'pointer to struct data'."
c->pData->wsDate = calloc(80, sizeof(char));
c->pData->__sizeM_Details = numRecords;
c->pData->M_Details = calloc((numRecords + 1) , sizeof(m_Param));
}
void freemem(REQUEST *c, int numRecords)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}
There's several fundamental problems, here:
In allocate(), all that memory you're malloc()ing is being lost at the end of your function, because you're assigning it to a local variable, c, which gets destroyed at the end of your function. You never use the address of the struct with automatic storage duration that you pass into the function. If you're passing the address of an object with automatic storage duration, then you should malloc() memory for the members, but not for the struct itself, since it obviously already has memory.
Then, in freemem(), you attempt to free() the memory associated with b, which is a struct with automatic storage duration. You can only free() memory that you've dynamically allocated.
You have a curious comment in allocate(), "this is just a pointer, should it not just allocate 4 bytes and continue?". If you're on a system with 32 bit pointers, then that is indeed what you allocated, but c->pData is a pointer to struct data which looks like it needs 28 bytes on a 32 bit machine, so you should be allocating a lot more than 4 bytes for it. Lines like c->pData->wsDate = ... seem to indicate that you're well aware it's a pointer to a struct data, so it's really unclear why you think you should only be allocating 4 bytes. When you allocate memory for an ANYTHING * to point to, then you need to allocate enough memory for an ANYTHING, not for an ANYTHING *, i.e. enough memory for the thing it's going to point to. The fact that you're trying to assign the memory to your pointer in the first place proves that you already have the memory for your pointer, otherwise you wouldn't be able to do that (providing that you haven't messed up some previous allocation, of course).
You never check the return from malloc() and calloc(), and you should.
Names beginning with a double underscore are always reserved for the implementation, so you should call __sizeM_Details something else.
sizeof(char) is 1 by definition, so there's never any need to use it.
It's unclear why you're allocating memory for numRecords + 1 of your struct details, rather than just numRecords as would seem intuitive. Perhaps you're looking to set that last one to NULL as a sentinel value, but if you're already storing the number of records in your struct, then this isn't really necessary.
Here's what your code ought to look like:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
void allocate(REQUEST * c, const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST b;
allocate(&b, 10);
freemem(&b);
return 0;
}
void allocate(REQUEST * c, const int numRecords)
{
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
}
If allocating automatic storage for b was a mistake, and you really do want to dynamically allocate everything, including your struct request, then it should look like this:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
REQUEST * allocate(const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST * b = allocate(10);
freemem(b);
return 0;
}
REQUEST * allocate(const int numRecords)
{
REQUEST * c = malloc(sizeof *c);
if ( !c ) {
perror("couldn't allocate memory for c");
exit(EXIT_FAILURE);
}
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
return c;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}
So the problem at hand is to convert a string of digits in the format YYYYMMDD to
a struct tm type member within some other structure. Truth is, I really only care
about getting a struct tm with reasonable values in it.
Consider the following struct :
typedef struct some_node {
char somestring[64];
char anotherstring[128];
struct tm date_one;
struct tm date_two;
int some_val;
struct some_node *prev;
struct some_node *next;
} some_node_t;
Inside there I have two members of type struct tm from the time.h header. Seems
very reasonable. Also there are pointer members in there to make a linked list
however that isn't the issue.
So I create the first node in my yet to be created linked list like so :
/* begin the linked list of some_node_t */
struct some_node *t_head =
calloc( (size_t) 1, sizeof( some_node_t ) );
if ( t_head == NULL ) {
/*Memory allocation fault */
printf ( " FAIL : Memory allocation fault at %s(%d)\n",
__FILE__, __LINE__ );
exit ( EXIT_FAILURE );
}
/* I used calloc above which zero fills memory so these
* next lines are not really needed. Better safe than sorry. */
t_head->some_val = 0;
t_head->prev = NULL;
t_head->next = NULL;
Then I can stuff char data into the two char members :
strcpy ( t_head->somestring, "birthday" );
strcpy ( t_head->anotherstring, "19981127" );
No problem there.
Messing with the conversion of a string to a struct tm seems reasonable within a
function as I have to do it twice perhaps.
Therefore I write this :
int timestr_to_tm ( struct tm **date_val, char *yyyymmdd ) {
/* assume 8 digits received in format YYYYMMDD */
int j, date_status = -1;
char yyyy[5]="0000";
char mm[3]="00";
char dd[3]="00";
/* copy over the year digits first */
for ( j=0; j<4; j++ )
yyyy[j]=yyyymmdd[j];
/* month digits */
mm[0]=yyyymmdd[4];
mm[1]=yyyymmdd[5];
/* day digits */
dd[0]=yyyymmdd[6];
dd[1]=yyyymmdd[7];
*(date_val)->tm_year = atoi(yyyy) - 1900;
*(date_val)->tm_mon = atoi(mm) - 1;
*(date_val)->tm_mday = atoi(dd);
*(date_val)->tm_hour = 0;
*(date_val)->tm_min = 0;
*(date_val)->tm_sec = 0;
*(date_val)->tm_isdst = -1;
return 0;
}
So my hope here is that I can pass a pointer to a pointer to the member date_one
within t_node to that function.
if ( timestr_to_tm ( &(t_node->date_one), "19981127" ) < 0 ) {
/* deal with a bad date conversion */
}
Well my compiler has a fit here. Claiming :
error: argument #1 is incompatible with prototype:
Perhaps I should have &t_head->date_one but I think that the pointer dereference
operator "->" takes precedence over the "address of" operator. Perhaps it is bad
policy to even attempt to pass a pointer to a member within a struct?
Even worse, within the function timestr_to_tm() I get :
error: left operand of "->" must be pointer to struct/union
in those lines where I try to assign values into the struct tm variable.
I tried all this without passing pointers and the process works however upon
return there is nothing in the struct tm member. So I am wondering, what am
I missing here ?
If you really want to pass a pointer to a pointer to a struct tm, you can, you just need to create a pointer variable to hold the pointer and pass a pointer to that:
struct tm *pointer = &t_node->date_one;
if ( timestr_to_tm ( &pointer, "19981127" ) < 0 ) {
...
The question is why? You don't need the extra level of indirection as you're not trying to change the pointer, you just want to fill in the struct tm within the node. So just use a single pointer:
int timestr_to_tm ( struct tm *date_val, char *yyyymmdd ) {
:
date_val->tm_year = atoi(yyyy) - 1900;
:
then you can call it with a simple pointer and don't need to create an extra pointer variable:
if ( timestr_to_tm ( &t_node->date_one, "19981127" ) < 0 ) {
...
I think that the pointer dereference operator -> takes precedence over the "address of" operator
It does, so does it over the dereference, * operator. So this, for example:
*(date_val)->tm_mday = atoi(dd);
should be
(*date_val)->tm_mday = atoi(dd);
But: Why would you do this? Why not pass a pointer to the struct tm, and use -> without one more level of indirection?
Since I'm too lazy to understand the question, I'll just add this unrelated example which hopefully helps to clear things up. This is very straightforward, if you use the correct syntax and level of indirection.
typedef struct _node node_t;
struct _node {
node_t* next;
int a;
};
void fill_in_int(int* pointer_to_int) {
*pointer_to_int = 42;
}
void populate_all_nodes(node_t* list, int a_value) {
node_t* node;
for (node=list; node; node = node->next) {
fill_in_int( &(node->a) ); // Pass pointer to member a in node
}
}