Memory allocation problem

R

RubenDV

I am writing code for a dictionary type in c, but i have some problems
allocating the memory for it. The dictionary type itself is a struct
with the following contents:

typedef struct {
char ** keys;
char ** content;
int count; /* Amount of space actually used */
int allocated_space; /* Amount of space allocated for the keys and
content */
} dict_t;

The function that allocates the memory goes like this:

dict_t * dictWithAllocatedSpace(dict_t * dictionary, int size)
{
dictionary = (dict_t *)malloc(sizeof(dict_t));
dictionary->allocated_space = size;
dictionary->keys = (char **)malloc(size);
dictionary->content = (char **)malloc(size);
dictionary->count = 0;
return dictionary;
}

when this function is executed the pointer it returns is not NULL, but
when i try to access one of its members, i get a bus error. I probably
made a terrible mistake, but i have no idea what that could be.
Any help is appreciated!

Ruben
 
G

Giannis Papadopoulos

RubenDV said:
I am writing code for a dictionary type in c, but i have some problems
allocating the memory for it. The dictionary type itself is a struct
with the following contents:

typedef struct {
char ** keys;
char ** content;
int count; /* Amount of space actually used */
int allocated_space; /* Amount of space allocated for the keys and
content */
} dict_t;

The function that allocates the memory goes like this:

dict_t * dictWithAllocatedSpace(dict_t * dictionary, int size)
{
dictionary = (dict_t *)malloc(sizeof(dict_t));
dictionary->allocated_space = size;
dictionary->keys = (char **)malloc(size);
dictionary->content = (char **)malloc(size);
dictionary->count = 0;
return dictionary;
}

Let's rephrase it.

dict_t* dictWithAllocatedSpace(int size)
{
dict_t *dictionary = malloc(sizeof *dictionary); /* do not cast malloc */
if (dictionary==NULL) /* always check for NULL */
{
return NULL;
}
dictionary->allocated_space = size;
dictionary->keys = malloc(size*sizeof *(dictionary->keys));
if (dictionary->keys==NULL)
{
free(dictionary);
return NULL;
}
dictionary->content = malloc(size*sizeof *(dictionary->content));
if (dictionary->content==NULL)
{
free(dictionary->keys);
free(dictionary);
return NULL;
}
dictionary->count = 0;
return dictionary;
}
when this function is executed the pointer it returns is not NULL, but
when i try to access one of its members, i get a bus error. I probably
made a terrible mistake, but i have no idea what that could be.
Any help is appreciated!

After the changes above, you are sure that if you get a NULL, something
has gone wrong. Check if NULL is returned...

If this does not solve anything, then post more code...
 
R

RubenDV

Yes it works now. But could you explain some more where i was wrong? I
would not want to make the same mistakes again. And thanks a lot for
helping me out!
 
M

Michael Mair

RubenDV said:
Yes it works now. But could you explain some more where i was wrong? I
would not want to make the same mistakes again. And thanks a lot for
helping me out!

Please quote sufficient context -- otherwise people may
not know what you talk about. In this case, it becomes
unreasonably hard to point you to your error in the code.

For once, I will quote the relevant parts of your original
message.
typedef struct {
char ** keys;
char ** content;
int count; /* Amount of space actually used */
int allocated_space; /* Amount of space allocated for the keys and
content */
} dict_t;

The function that allocates the memory goes like this:

dict_t * dictWithAllocatedSpace(dict_t * dictionary, int size)
> {

As you did not show us a compiling minimal example, we
are reduced to guesses. In this case, though, there is
a guess:
You have a completely useless parameter: dictionary.
If you tried something along the lines

dict_t *mydict;
if (NULL == dictWithAllocatedSpace(mydict, DICT_SIZE))
{
.... /* error handling */
}

then you passed an uninitialised value (the arbitrary value
mydict has without initialisation); this "value" became the
value of dictionary; you then overwrote dictionary's value.
However, the original variable, mydict, was not modified by
what happened to a copy of its value.
So, in order to modify mydict, you have to pass its address.
Say, we have

dict_t * dictWithAllocatedSpace(dict_t ** pdict, int size)
{
dict_t *dictionary;
*pdict = NULL;
dictionary = (dict_t *)malloc(sizeof(dict_t));

Bad: Casting the return value of malloc().
Use malloc() like this:
dictionary = malloc(sizeof *dictionary);
Worse: No checking of the return value against NULL.
dictionary->allocated_space = size;
dictionary->keys = (char **)malloc(size);
dictionary->content = (char **)malloc(size);

Now, apart from
dictionary->keys = malloc(size * sizeof *dictionary->keys);
the not checking for return values may really bite you
here:
You return a non-null pointer if the first allocation
was successful but the second and third allocations may
have gone wrong.
dictionary->count = 0;

*pdict = dictionary;
return dictionary;
}

Cheers
Michael
 

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

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,226
Latest member
KristanTal

Latest Threads

Top