Allocating memory for struct - when?

F

fix

Hi all,
I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells me
that the code causes the problem is in the malloc function.
Is there any general rules that tell me when to allocate memory?
I thought I don't have to if it is a variable that's not a pointer, and
I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't have
to do so, but if I want to use a pointer so that the array can be
dynamic, I shall use *array and allocate the amount of memory I want,
like array = malloc(sizeof(data_type) * number_of_item), right?
And if I am storing a "string" (char array) in a struct, what happens.
I declared it as:

typedef struct {
void *obj;
char key[];
} HashTableEntry;

What I do to initialize the object is:

HashTableEntry *hte = malloc(sizeof(HashTableEntry));
// "key" is a defined char array
strcpy(hte->key, key);
hte->obj = NULL;

How do the program know how much memory have to be allocated for the
HashTableEntry? It seems that it is dynamically sized, it depends on the
char array key.
And one more thing is, I can't reverse the order of the two members, if
I do so, the program does not compile. Is there any link between the
problem I have said above?
Thanks all!
 
K

Karthik

fix said:
Hi all,
I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells me
that the code causes the problem is in the malloc function.
Is there any general rules that tell me when to allocate memory?
I thought I don't have to if it is a variable that's not a pointer, and
I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't have
to do so, but if I want to use a pointer so that the array can be
dynamic, I shall use *array and allocate the amount of memory I want,
like array = malloc(sizeof(data_type) * number_of_item), right?
And if I am storing a "string" (char array) in a struct, what happens.
I declared it as:

typedef struct {
void *obj;
char key[];
Whatz this ???
} HashTableEntry;

What I do to initialize the object is:

HashTableEntry *hte = malloc(sizeof(HashTableEntry));
// "key" is a defined char array
strcpy(hte->key, key);

This is directly related to the problem 1 mentioned before. You are
not allocating memory for the field - 'key' . Try this :


typedef struct {
void *obj;
char * key;
} HashTableEntry;

HashTableEntry *hte = malloc(sizeof(HashTableEntry));
// "key" is a defined char array
key = malloc(sizeof(char) * MAX_CHAR_LEN);
strcpy(hte->key, key);
hte->obj = NULL;


This should help ..
Dont forget to delete the pointers when deleting the object.


free(hte) ; // Memory leak


free(obj);
free(key);
free(hte);
// Pretty cool . But you still need to make sure that indeed the
fields were allocated to be freed...

HTH
 
K

Karthik

Karthik said:
fix said:
Hi all,
I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells me
that the code causes the problem is in the malloc function.
Is there any general rules that tell me when to allocate memory?
I thought I don't have to if it is a variable that's not a pointer,
and I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't
have to do so, but if I want to use a pointer so that the array can be
dynamic, I shall use *array and allocate the amount of memory I want,
like array = malloc(sizeof(data_type) * number_of_item), right?
And if I am storing a "string" (char array) in a struct, what happens.
I declared it as:

typedef struct {
void *obj;
char key[];

Whatz this ???
} HashTableEntry;

What I do to initialize the object is:

HashTableEntry *hte = malloc(sizeof(HashTableEntry));
// "key" is a defined char array
strcpy(hte->key, key);


This is directly related to the problem 1 mentioned before. You are
not allocating memory for the field - 'key' . Try this :


typedef struct {
void *obj;
char * key;
} HashTableEntry;

HashTableEntry *hte = malloc(sizeof(HashTableEntry));
// "key" is a defined char array
key = malloc(sizeof(char) * MAX_CHAR_LEN);
Instead - better -
key = malloc(sizeof(char) * (strlen(key) + 1 ));
// Remember the '\0' char
 
R

Régis Troadec

fix said:
Hi all,
Hi,

[snipped]

typedef struct {
void *obj;
char key[];

key is for the moment an array whose the number of elements is unknown, it's
an incomplete type (say, flexible array). A thing you can do here is to
precise the number of elements you want, char key[50]; for example ( a
#define directive may also help), or use a pointer.
} HashTableEntry;

What I do to initialize the object is:
HashTableEntry *hte = malloc(sizeof(HashTableEntry));

/* hte tot test */
if (hte != NULL)
{
// "key" is a defined char array
strcpy(hte->key, key);

Assuming hte->key has now a complete type with a well-known size like said
above, using strncpy() instead of strcpy() will prevent of writing outside
the bounds of the hte->key array:

/* 50-1 to write at least one null terminating character in hte->key, only
49 characters
from key are copied into hte->key */
strncpy(hte->key, key, 50-1);
hte->obj = NULL;

How do the program know how much memory have to be allocated for the
HashTableEntry? It seems that it is dynamically sized, it depends on the
char array key.

Your structure HashTableEntry contains a pointer to a void element and,
still assuming the member key in the structure is now sized to 50, 50 char
contiguous elements. The compiler knows the space it needs to store such
things (IOW, he knows how many bytes are necessary to store an adress of a
void element and 50 characters. Furthermore, the compiler adds padding bits
between the members of your structure (not before the first member, here
obj) to correctly align the data in memory.
And one more thing is, I can't reverse the order of the two members, if
I do so, the program does not compile. Is there any link between the
problem I have said above?

Yes, since the key member was an incomplete type (remember, flexible array)
and placed first in the structure, the compiler was unable to determine the
size of key and where he would have stored obj. If key is placed in the last
position, it makes sense : I don't know the real policy used by the
compiler, but it can view key as a pointer to a char.


Regis
 
R

Régis Troadec

fix said:

Hi again,

I forgot to answer to other points.
I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells me
that the code causes the problem is in the malloc function.
Is there any general rules that tell me when to allocate memory?

The general policy is to allocate memory for your pointers as soon as you
need to use them and desallocate them as soon as you don't need them anymore
in your program. IMHO, by using pointers, allocating all the needed memory
at the beginning of a program to desallocate it at the end is nonsense.
I thought I don't have to if it is a variable that's not a pointer, and
I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't have
to do so, but if I want to use a pointer so that the array can be
dynamic, I shall use *array and allocate the amount of memory I want,

....or array : array->something against (*array).something, which one is
easier to read?
like array = malloc(sizeof(data_type) * number_of_item), right?

Right.

Regis
 
F

fix

Karthik said:
Karthik said:
fix said:
Hi all,
I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells
me that the code causes the problem is in the malloc function.
Is there any general rules that tell me when to allocate memory?
I thought I don't have to if it is a variable that's not a pointer,
and I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't
have to do so, but if I want to use a pointer so that the array can
be dynamic, I shall use *array and allocate the amount of memory I
want, like array = malloc(sizeof(data_type) * number_of_item), right?
And if I am storing a "string" (char array) in a struct, what happens.
I declared it as:

typedef struct {
void *obj;
char key[];


Whatz this ???

Just like the function header some_fct(int some_int, char char_array[]),
I can't do that?
Instead - better -
key = malloc(sizeof(char) * (strlen(key) + 1 ));
// Remember the '\0' char

Actually I want to store the string in the struct, not pointing to
somewhere out there, is that possible?
 
F

fix

Régis Troadec said:


Hi again,

I forgot to answer to other points.

I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells me
that the code causes the problem is in the malloc function.
Is there any general rules that tell me when to allocate memory?


The general policy is to allocate memory for your pointers as soon as you
need to use them and desallocate them as soon as you don't need them anymore
in your program. IMHO, by using pointers, allocating all the needed memory
at the beginning of a program to desallocate it at the end is nonsense.

I thought I don't have to if it is a variable that's not a pointer, and
I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't have
to do so, but if I want to use a pointer so that the array can be
dynamic, I shall use *array and allocate the amount of memory I want,


...or array : array->something against (*array).something, which one is
easier to read?

How could I use it like an array?
I can do array[0], .... array[5] if I declared int array[10],
and *array to access the data and array++ to go to the next one.
 
F

fix

Régis Troadec said:
Hi all,

Hi,

[snipped]


typedef struct {
void *obj;
char key[];


key is for the moment an array whose the number of elements is unknown, it's
an incomplete type (say, flexible array). A thing you can do here is to
precise the number of elements you want, char key[50]; for example ( a
#define directive may also help), or use a pointer.

But I don't know how long the char array will be and I want to store it
in the struct.
 
R

Regis Troadec

fix said:
key is for the moment an array whose the number of elements is unknown, it's
an incomplete type (say, flexible array). A thing you can do here is to
precise the number of elements you want, char key[50]; for example ( a
#define directive may also help), or use a pointer.

But I don't know how long the char array will be and I want to store it
in the struct.

Don't you know at least the maximum size?

Regis
 
R

Regis Troadec

fix said:
I thought I don't have to if it is a variable that's not a pointer, and
I have to if it is.
I am a bit confused about the arrays particularly.
In normal situations, memory is allocated for array[10] and I don't have
to do so, but if I want to use a pointer so that the array can be
dynamic, I shall use *array and allocate the amount of memory I want,


...or array : array->something against (*array).something, which one is
easier to read?

How could I use it like an array?
I can do array[0], .... array[5] if I declared int array[10],
and *array to access the data and array++ to go to the next one.

It was a general comment about pointers. If array is a pointer in your case,
you can still use the subscript notation array[i-th] to access the elements
when it's allocated.

Regis
 
C

Chris Torek

After carefully matching up the > marks, I believe that:
fix wrote:
typedef struct {
void *obj;
char key[];
} HashTableEntry;
and:

Just like the function header some_fct(int some_int, char char_array[]),
I can't do that?

Not in C89. In C99, it is allowed, and is a new construct called
a "flexible array member" of a structure.

Note that the structure type (which is unnamed) is a complete type,
but is always smaller than the "final" size you really want to use.
Such structures essentially always must be allocated via malloc(),
and dealt with through pointers. Suppose that the "key" is a
C-style string that contains four characters such as "abcd", and
thus is five bytes long: {'a', 'b', 'c', 'd', '\0'}. Given a
pointer to the alias for the unnamed structure type:

HashTableEntry /* an alias for struct <name_not_available> */ *p;

you would then write:

p = malloc((1 * sizeof *p) + 5);

or equivalently:

p = malloc(sizeof *p + 5);

The first form follows the time-tested, "comp.lang.c approved" :)
idiom of:

var = malloc(N * sizeof *var);

where N is the number of objects to allocate. Flexible-array-member
structures almost invariably have to be allocated one at a time
anyway (so that N must always be 1) and need some additional number
added to account for the array added to the end. To continue to
follow the "comp.lang.c idiom", as it were, it really should read:

var = malloc(sizeof *var + N * sizeof *var->flexible_array_member);

or in this case:

p = malloc(sizeof *p + 5 * sizeof *p->key);

since the goal is to allocate, in one swoop, both one (1) "struct"
object *and* just enough extra space for N (5, here) array-elements
in the F.A.M. appended to the structure. But we know for certain
(because the language definition says so) that sizeof(char) is
just 1, and 5 * 1 is of course 5.

In C89 (also called C90 sometimes), flexible array members do not
exist. As you can see in the FAQ, there is a "cheat" that usually
works, in which one declares the structure as having an array of
size 1:

typedef struct HashTableEntry HashTableEntry;

struct HashTableEntry {
void *obj;
char key[1];
};

but this is technically illegal, despite the extremely good chance
of getting away with it (see FAQ #2.6). In this case, the array
p->key has one element already -- which is just enough room for
the '\0' that terminates any C-style string -- so the call would
look like:

p = malloc(sizeof *p + 4); /* '\0' already accounted-for */

This again uses the fact that sizeof(char) is just 1 -- if the
faked F.A.M. had some element-type other than "char", e.g.:

struct zog {
int zog_len; /* number of zogs */
int zog_val[]; /* and the zogs, as F.A.M. */
};

then we would need code more like:

struct zog *p;
...
p = malloc(sizeof *p + n * sizeof p->zog_val[0]);
if (p == NULL) ... handle memory-allocation failure ...
p->zog_len = n;
... set up p->zog_val for i in [0..n) ...

In this malloc() call, I prefer suffixing p->zog_val with [0],
rather than writing the "*" in front, but this is just a style
issue.

Finally, I should note that the:
function header some_fct(int some_int, char char_array[])

does *not* declare "char_array" as an array. See section 6 of the
FAQ (in particular question 6.4).
 
A

Al Bowers

fix said:
R?is Troadec wrote:

"fix" <[email protected]> a ?rit dans le message de

Hi all,

Hi,

[snipped]



typedef struct {
void *obj;
char key[];


key is for the moment an array whose the number of elements is unknown, it's
an incomplete type (say, flexible array). A thing you can do here is to
precise the number of elements you want, char key[50]; for example ( a
#define directive may also help), or use a pointer.


But I don't know how long the char array will be and I want to store it
in the struct.

Then I suggest you make the member key type char *.
You then allocated key to strlen of the key string + 1.
I would put the allocations in a function with one parameter
being the key string and the other parameter being a pointer
to the void *obj. The function would return a pointer to the
newly allocated and assigned HastTableEntry.

Example:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
void *obj;
char *key;
}HashTableEntry;

typedef struct EXAMPLEDATA
{
char ip[16];
char name[64];
}EXAMPLEDATA;

HashTableEntry *addHashTableEntry(const char *key, void *data);
void freeHashTableEntry(HashTableEntry **node);

int main(void)
{
EXAMPLEDATA data = {"192.168.42.007","www.abcd.com"};
HashTableEntry *node = NULL;

/* For example say key is AbcDeFG123 */
node = addHashTableEntry("AbcDeFG123", &data);
if(node)
printf("node->key = \"%s\"\n"
"node->obj points to struct containing an\n"
"ip of \"%s\" and a\ndomain name of \"%s\"\n",
node->key,((EXAMPLEDATA *)node->obj)->ip,
((EXAMPLEDATA *)node->obj)->name);
freeHashTableEntry(&node);
puts("\nThe allocations have been freed\nExiting....\n");
return 0;
}

HashTableEntry *addHashTableEntry(const char *key, void *data)
{
HashTableEntry *new;

if((new = malloc(sizeof *new)) == NULL) return NULL;
if((new->key = malloc(strlen(key)+1)) == NULL)
{
free(new);
return NULL;
}
strcpy(new->key,key);
new->obj = data;
return new;
}

void freeHashTableEntry(HashTableEntry **node)
{
if(*node) free((*node)->key);
free(*node);
*node = NULL;
return;
}
 
O

Old Wolf

fix said:
I am writing a program using some structs, it is not running and I
believe it is because there's some memory leak - the debugger tells me
that the code causes the problem is in the malloc function.
typedef struct {
void *obj;
char key[];
} HashTableEntry;

BTW, you can't have arrays of these.
What I do to initialize the object is:

HashTableEntry *hte = malloc(sizeof(HashTableEntry));
// "key" is a defined char array
strcpy(hte->key, key);
hte->obj = NULL;

What you should be doing is:
HashTableEntry *hte = malloc(strlen(key) + 1 + sizeof *hte);
strcpy(hte->key, key);
hte->obj = NULL;

Note that sizeof(*hte) is the same as sizeof(void*), the member "key"
does not have a size that the compiler knows about. You won't be
able to access the size of the entry later on in your code.
Because of this, you can't safely put a new value into the key (unless
it has the same length). So I would consider making key "const char"
instead of "char" (and casting it in the call to strcpy).
And one more thing is, I can't reverse the order of the two members

Obviously not, how would the compiler know how much memory to
leave before the start of "obj" ?

If this is all confusing to you, you might want to consider
the other poster's suggestion of having "char *key;" and allocating
key with malloc too; although it seems to me that this is a perfect
example of a situation that flexible array members were designed for.
 
F

fix

Chris Torek wrote:
... snip ..
HashTableEntry /* an alias for struct <name_not_available> */ *p;

you would then write:

p = malloc((1 * sizeof *p) + 5);

or equivalently:

p = malloc(sizeof *p + 5);

So in short, I have to allocate memory for the sizeof(the_struct) +
sizeof(flexible_array_member). Maybe that's why my program just crashes
if I allocate memory just for the struct. But I wonder why
sizeof(the_struct) will only return the size without the flexible array
member, is it designed to be? It looked a bit odd to me.

... snip ..
Finally, I should note that the:

function header some_fct(int some_int, char char_array[])


does *not* declare "char_array" as an array. See section 6 of the
FAQ (in particular question 6.4).

OK, I got it, thanks.
 
F

fix

Regis said:
key is for the moment an array whose the number of elements is unknown,
it's
an incomplete type (say, flexible array). A thing you can do here is to
precise the number of elements you want, char key[50]; for example ( a
#define directive may also help), or use a pointer.

But I don't know how long the char array will be and I want to store it
in the struct.


Don't you know at least the maximum size?

Regis
It is the users to decide, I really wouldn't know in advance.
 
R

Ross Kendall Axe

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

fix wrote:
|
| Chris Torek wrote:
| .. snip ..
|
|> HashTableEntry /* an alias for struct <name_not_available> */ *p;
|>
|>you would then write:
|>
|> p = malloc((1 * sizeof *p) + 5);
|>
|>or equivalently:
|>
|> p = malloc(sizeof *p + 5);
|>
|
|
| So in short, I have to allocate memory for the sizeof(the_struct) +
| sizeof(flexible_array_member). Maybe that's why my program just crashes
| if I allocate memory just for the struct. But I wonder why
| sizeof(the_struct) will only return the size without the flexible array
| member, is it designed to be? It looked a bit odd to me.
|

Well, because sizeof(flexible_array_member) is unknown, that what makes
it flexible. So instead, sizeof(the_struct) just gives you the size of
the stuff that *is* known. Of course, sizeof(*flexible_array_member)
(one element of the array) is known, so the size of the whole lot is
sizeof(the_struct)+n*sizeof(*flexible_array_member), where n is a value
unknown to the compiler.

Ross
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFAlvl99bR4xmappRARAvhwAJ0eZYrRtbOiHwVA6mvlj4xKsNabPACdHtxv
hsHwRMJW4hTrc8xCnTA9lz0=
=TZvV
-----END PGP SIGNATURE-----
 

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,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top