malloc Q

K

Kamus of Kadizhar

This is probably pretty silly for those in the know, but it's been a while
since I've muddled about with malloc....

I have the following snippet of code:

char *letters_array[6];

......

int fill_letters(char *letterString,char *buffer) {
letterString = malloc(strlen(buffer)+1);
sprintf(letterString,"%s",buffer);
printf("fill: >%s<, %d\n",buffer,strlen(buffer)+1);
}

int load_default_charset() {
printf("in load_default_charset\n");
fill_letters(letters_array[0],"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
printf("filled: >%s<,\n",letters_array[0]);
...
return TRUE;
}

It seems that the memory allocated in fill_letters is being released as
soon as that function returns (the printf in load_default_charset shows
(NULL) for letters_array[0]). I would have thought that since I'm passing
pointers the malloc would be "sticky" and not be freed until a call to
free().

So, how do I rewrite the code to insure that the memory remains allocated?
I could pass just the index for letters_array, but for maintenance and
readability I would prefer to pass the pointer itself.

--Kamus
 
C

Christopher Benson-Manica

Kamus of Kadizhar said:
This is probably pretty silly for those in the know, but it's been a while
since I've muddled about with malloc....
I have the following snippet of code:
char *letters_array[6];

int fill_letters( char *letterString, char *buffer ) {
letterString=malloc( strlen(buffer)+1 );
^^^^^^^^^^^^ What if malloc() fails? Kablooie?
sprintf( letterString, "%s", buffer );
printf( "fill: >%s<, %d\n", buffer, strlen(buffer)+1 );
}
int load_default_charset() {
printf( "in load_default_charset\n" );
fill_letters( letters_array[0], "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
printf( "filled: >%s<,\n", letters_array[0] );
...
return TRUE;
^^^^ presumably #define'd appropriately?
It seems that the memory allocated in fill_letters is being released as
soon as that function returns (the printf in load_default_charset shows
(NULL) for letters_array[0]). I would have thought that since I'm passing
pointers the malloc would be "sticky" and not be freed until a call to
free().

(I've taken the liberty of applying my code-spacing paradigm to yours.)

malloc() is behaving the way you think it should - the mistake you're
making is in how you're passing its return value around. No matter
what happens in fill_letters, letters_array[0] will be unchanged:
parameters are passed by value in C, so assigning to letterString has
no meaning outside fill_letters(). What you want is something like

int fill_letters( char **letterString, char *buffer ) {
*letterString=malloc( strlen(buffer) );
...
}

and

int load_default_charset() {
...
fill_letters( &letters_array[0], ... );
...
}

See how this works?
 
C

Christopher Benson-Manica

Christopher Benson-Manica said:
int fill_letters( char **letterString, char *buffer ) {
*letterString=malloc( strlen(buffer) );
strlen(buffer)+1, of course, as in the
original! *sigh*
 
D

Darrell Grainger

This is probably pretty silly for those in the know, but it's been a while
since I've muddled about with malloc....

I have the following snippet of code:

char *letters_array[6];

.....

int fill_letters(char *letterString,char *buffer) {
letterString = malloc(strlen(buffer)+1);
sprintf(letterString,"%s",buffer);
printf("fill: >%s<, %d\n",buffer,strlen(buffer)+1);
}

The problem is in this function. The variable letterString is a COPY of
letters[0]. The result of malloc is being stored in the copy and not the
original. When you leave the scope of fill_letters the result of malloc is
lost. One possible solution is to change fill_letters to take a char**,
malloc to *letterString and pass in &letters_array[0].
int load_default_charset() {
printf("in load_default_charset\n");
fill_letters(letters_array[0],"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
printf("filled: >%s<,\n",letters_array[0]);
...
return TRUE;
}

It seems that the memory allocated in fill_letters is being released as
soon as that function returns (the printf in load_default_charset shows
(NULL) for letters_array[0]). I would have thought that since I'm passing
pointers the malloc would be "sticky" and not be freed until a call to
free().

So, how do I rewrite the code to insure that the memory remains allocated?
I could pass just the index for letters_array, but for maintenance and
readability I would prefer to pass the pointer itself.

--Kamus
 
K

Kamus of Kadizhar

Kamus of Kadizhar said:
This is probably pretty silly for those in the know, but it's been a
while since I've muddled about with malloc....
I have the following snippet of code:
char *letters_array[6];

int fill_letters( char *letterString, char *buffer ) {
letterString=malloc( strlen(buffer)+1 );
^^^^^^^^^^^^ What if malloc() fails? Kablooie?

Well, actually, the call to malloc in the original is a wrapper to the
that handles that. I didn't want to muddy the waters....
sprintf( letterString, "%s", buffer ); printf( "fill: >%s<, %d\n",
buffer, strlen(buffer)+1 ); }
int load_default_charset() {
printf( "in load_default_charset\n" ); fill_letters(
letters_array[0], "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ); printf( "filled:
%s<,\n", letters_array[0] ); ...
return TRUE;
^^^^ presumably #define'd appropriately?
It seems that the memory allocated in fill_letters is being released as
soon as that function returns (the printf in load_default_charset shows
(NULL) for letters_array[0]). I would have thought that since I'm
passing pointers the malloc would be "sticky" and not be freed until a
call to free().

(I've taken the liberty of applying my code-spacing paradigm to yours.)

malloc() is behaving the way you think it should - the mistake you're
making is in how you're passing its return value around. No matter what
happens in fill_letters, letters_array[0] will be unchanged: parameters
are passed by value in C, so assigning to letterString has no meaning
outside fill_letters(). What you want is something like

int fill_letters( char **letterString, char *buffer ) {
*letterString=malloc( strlen(buffer) ); ...
}

and

int load_default_charset() {
...
fill_letters( &letters_array[0], ... ); ...
}

See how this works?

But wait a minute - letters_array is an array of pointers to char. So
wouldn't I be passing a pointer by passing letters_array[0]? And wouldn't
&letters_array[0] be the address of the array itself (and thus a char **)?
That was my original thought.

God that makes my brain hurt. And to think I used to teach this
stuff.... Senility is a terrible thing. :)

--Kamus
 
L

Lewis Bowers

Kamus said:
This is probably pretty silly for those in the know, but it's been a while
since I've muddled about with malloc....

I have the following snippet of code:

char *letters_array[6];

.....

int fill_letters(char *letterString,char *buffer) {
letterString = malloc(strlen(buffer)+1);
sprintf(letterString,"%s",buffer);
printf("fill: >%s<, %d\n",buffer,strlen(buffer)+1);
}

int load_default_charset() {
printf("in load_default_charset\n");
fill_letters(letters_array[0],"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
printf("filled: >%s<,\n",letters_array[0]);
...
return TRUE;
}

It seems that the memory allocated in fill_letters is being released as
soon as that function returns (the printf in load_default_charset shows
(NULL) for letters_array[0]). I would have thought that since I'm passing
pointers the malloc would be "sticky" and not be freed until a call to
free().

So, how do I rewrite the code to insure that the memory remains allocated?
I could pass just the index for letters_array, but for maintenance and
readability I would prefer to pass the pointer itself.

The problem here is not that the memory was not allocated, it is that once you

exit the function fill_letters, the value returned by malloc, representing a
pointer
to the space is lost. Although it may impair your readibility, you should
redesign
the function. For example, define the function as:


int fill_letters(char **letterString,char *buffer) {
*letterString = malloc(strlen(buffer)+1);
if(*letterString == NULL) return 0;
sprintf(*letterString,"%s",buffer);
printf("fill: >%s<, %d\n",buffer,strlen(buffer)+1);
return 1;
}

Then modify the function load_default_charset to:

void load_default_charset(char **p) {
printf("in load_default_charset\n");
if(fill_letters( &p[0],"ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
printf("filled: >%s<,\n",p[0]);
else puts("Failure to store the charset");
}

And to use the functions:

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

/* Prototypes */
int fill_letters(char **letterString,char *buffer);
void load_default_charset(char **p);

int main(void)
{
char *letters_array[6];

load_default_charset(letters_array);
if(letters_array[0])
printf("\nletters_array[0] = \"%s\"\n",
letters_array[0]);
free(letters_array[0]);
return 0;
}

int fill_letters(char **letterString,char *buffer) {
*letterString = malloc(strlen(buffer)+1);
if(*letterString == NULL) return 0;
sprintf(*letterString,"%s",buffer);
printf("fill: >%s<, %d\n",buffer,strlen(buffer)+1);
return 1;
}

void load_default_charset(char **p) {
printf("in load_default_charset\n");
if(fill_letters( &p[0],"ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
printf("filled: >%s<,\n",p[0]);
else puts("Failure to store the charset");
}
 
L

Lewis Bowers

Kamus said:
Kamus of Kadizhar said:
This is probably pretty silly for those in the know, but it's been a
while since I've muddled about with malloc....
I have the following snippet of code:
char *letters_array[6];

int fill_letters( char *letterString, char *buffer ) {
letterString=malloc( strlen(buffer)+1 );
^^^^^^^^^^^^ What if malloc() fails? Kablooie?

Well, actually, the call to malloc in the original is a wrapper to the
that handles that. I didn't want to muddy the waters....
sprintf( letterString, "%s", buffer ); printf( "fill: >%s<, %d\n",
buffer, strlen(buffer)+1 ); }
int load_default_charset() {
printf( "in load_default_charset\n" ); fill_letters(
letters_array[0], "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ); printf( "filled:
%s<,\n", letters_array[0] ); ...
return TRUE;
^^^^ presumably #define'd appropriately?
It seems that the memory allocated in fill_letters is being released as
soon as that function returns (the printf in load_default_charset shows
(NULL) for letters_array[0]). I would have thought that since I'm
passing pointers the malloc would be "sticky" and not be freed until a
call to free().

(I've taken the liberty of applying my code-spacing paradigm to yours.)

malloc() is behaving the way you think it should - the mistake you're
making is in how you're passing its return value around. No matter what
happens in fill_letters, letters_array[0] will be unchanged: parameters
are passed by value in C, so assigning to letterString has no meaning
outside fill_letters(). What you want is something like

int fill_letters( char **letterString, char *buffer ) {
*letterString=malloc( strlen(buffer) ); ...
}

and

int load_default_charset() {
...
fill_letters( &letters_array[0], ... ); ...
}

See how this works?

But wait a minute - letters_array is an array of pointers to char. So
wouldn't I be passing a pointer by passing letters_array[0]? And wouldn't
&letters_array[0] be the address of the array itself (and thus a char **)?
That was my original thought.

Read faq: http://www.eskimo.com/~scs/C-faq/q4.8.html

You designed your function to accept a char * argument.
You call it with the argument letters_array[0]. This argument is a
copy of the value. You then modify that value with function malloc. The
copy is changed and then promply lost when you exit the function. The
original value in letters_array[0] remain unchanged.
 
K

Kamus of Kadizhar

Read faq: http://www.eskimo.com/~scs/C-faq/q4.8.html

You designed your function to accept a char * argument.
You call it with the argument letters_array[0]. This argument is a
copy of the value. You then modify that value with function malloc. The
copy is changed and then promply lost when you exit the function. The
original value in letters_array[0] remain unchanged.

OK, a light begins to dawn....

Thanks,

--Kamus
 

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,143
Latest member
SterlingLa
Top