error when allocating memory using a pointer inside a struct via a function

E

elmafiacs

I need some help with an error I'm getting...
Sorry if this is basic stuff, but I'm still a newbie on C programming
(working up, though).
Also, I'm using gcc as my compiler ('gcc t.c -o t', no strange stuff).
Sorry about the long subject, I didn't know how to explain it better...

struct small {
int num;
};

struct big {
struct small *small_thing;
};

void f(struct small **s)
{
s = malloc(sizeof(struct small));
memset(s, 0, sizeof(struct small));
s->num = 42;
}

main()
{
struct big *big_thing;

big_thing = malloc(sizeof(struct big));
memset(&big_thing, 0, sizeof(struct big));

f(&big_thing->small_thing);
printf("%i\n", big_thing->small_thing->n);
}

But when I do:
s->num = 42;
the compiler fails with error 'request for member 'num' in something
not an structure or union', and I don't know why.

I tried this way:

void f(struct small **s)
{
struct small *s_ptr;
s_ptr->num = 42;
memcpy(s, &s_ptr, sizeof(struct small));
}

I'm not sure, but I think that the second function is unnecessary. So,
how to fix the first function?

Thanks.
 
D

David Resnick

I need some help with an error I'm getting...
Sorry if this is basic stuff, but I'm still a newbie on C programming
(working up, though).
Also, I'm using gcc as my compiler ('gcc t.c -o t', no strange stuff).
Sorry about the long subject, I didn't know how to explain it better...

struct small {
int num;
};

struct big {
struct small *small_thing;
};

void f(struct small **s)
{
s = malloc(sizeof(struct small));
memset(s, 0, sizeof(struct small));
s->num = 42;
}

s is a pointer to a pointer to a struct small, not a pointer
to a struct small. Accordingly, you want this:

*s = malloc(sizeof **s);
memset(*s, 0, sizeof **s);
(*s)->num = 42;

And you should check the return value of malloc...

-David



-David
 
M

Martin Ambuhl

I need some help with an error I'm getting...
Sorry if this is basic stuff, but I'm still a newbie on C programming
(working up, though).
Also, I'm using gcc as my compiler ('gcc t.c -o t', no strange stuff).
Sorry about the long subject, I didn't know how to explain it better...

struct small {
int num;
};

struct big {
struct small *small_thing;
};

void f(struct small **s)
{
s = malloc(sizeof(struct small));
memset(s, 0, sizeof(struct small));
s->num = 42;
}

main()
{
struct big *big_thing;

big_thing = malloc(sizeof(struct big));
memset(&big_thing, 0, sizeof(struct big));

f(&big_thing->small_thing);
printf("%i\n", big_thing->small_thing->n);
}

But when I do:
s->num = 42;
the compiler fails with error 'request for member 'num' in something
not an structure or union', and I don't know why.

I tried this way:

void f(struct small **s)
{
struct small *s_ptr;
s_ptr->num = 42;
memcpy(s, &s_ptr, sizeof(struct small));
}

I'm not sure, but I think that the second function is unnecessary. So,
how to fix the first function?

Thanks.

Please don't post code that is not that which you have actually
compiled. Here is a start toward fixing your code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct small
{
int num;
};

struct big
{
struct small *small_thing;
};

void f(struct small **s)
{
*s = malloc(sizeof **s);
/* add code to check that *s != 0 */
memset(*s, 0, sizeof **s);
(*s)->num = 42;
}

int main(void)
{
struct big *big_thing;

big_thing = malloc(sizeof *big_thing);
/* add code to check that big_thing != 0 */
memset(&big_thing, 0, sizeof big_thing);

f(&big_thing->small_thing);
printf("%i\n", big_thing->small_thing->num);
free(big_thing->small_thing);
free(big_thing);
return 0;
}
 
A

Al Bowers

Martin said:
Please don't post code that is not that which you have actually
compiled. Here is a start toward fixing your code:

In addition to compiling, run and testing the code before posting can be
helpful
(but not final) in catching additional flaws. For example....
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct small
{
int num;
};

struct big
{
struct small *small_thing;
};

void f(struct small **s)
{
*s = malloc(sizeof **s);
/* add code to check that *s != 0 */
memset(*s, 0, sizeof **s);
(*s)->num = 42;
}

int main(void)
{
struct big *big_thing;

big_thing = malloc(sizeof *big_thing);
/* add code to check that big_thing != 0 */
memset(&big_thing, 0, sizeof big_thing);
Running and testing might identify the memset statement flaw
above. It should be:
memset(big_thing, 0 , sizeof big_thing);

And, as you suggested, code to catch dynamic memory allocations
with function malloc needs to be added to make execution of the code
safe. See the example below:
f(&big_thing->small_thing);
printf("%i\n", big_thing->small_thing->num);
free(big_thing->small_thing);
free(big_thing);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct small {
int num;
};

struct big {
struct small *small_thing;
};

void f(struct small **s)
{
*s = malloc(sizeof(struct small));
if(*s)
{
memset(*s, 0, sizeof(struct small));
(*s)->num = 42;
}
}

int main(void)
{
struct big *big_thing;

big_thing = malloc(sizeof(struct big));
if(big_thing)
{
memset(big_thing, 0, sizeof(struct big));
f(&big_thing->small_thing);
if(big_thing->small_thing)
printf("big_thing->small_thing->num = %i\n",
big_thing->small_thing->num);
free(big_thing->small_thing);
}
free(big_thing);
return 0;
}

Al Bowers
 
O

Old Wolf

Al said:
Running and testing might identify the memset statement flaw
above. It should be:
memset(big_thing, 0 , sizeof big_thing);

1) Running and testing isn't a great way of checking for
undefined behaviour

2) A statement: memset(foo, bar, sizeof foo); is wrong, unless
foo and &foo are the same address (ie. for an array).
It should be:

memset(big_thing, 0, sizeof *big_thing);

The OP (who has been snipped) had it correct.
IMHO, even better would be to use calloc instead of malloc.
 
A

Al Bowers

Old said:
Al Bowers wrote:




2) A statement: memset(foo, bar, sizeof foo); is wrong, unless
foo and &foo are the same address (ie. for an array).
It should be:

memset(big_thing, 0, sizeof *big_thing);

The OP (who has been snipped) had it correct.
I don't think so. The op code was:
struct big *big_thing;
big_thing = malloc(sizeof(struct big));
memset(&big_thing, 0, sizeof(struct big));

Is that correct?

I believe it should be:
memset(big_thing, 0, sizeof *big_thing);
or
memset(big_thing, 0, sizeof(struct big));
 
O

Old Wolf

Al said:
I don't think so. The op code was:


Is that correct?

I believe it should be:
memset(big_thing, 0, sizeof *big_thing);
or
memset(big_thing, 0, sizeof(struct big));

You're right. I think we got there in the end :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top