tags:

views:

2336

answers:

8

Someone here recently pointed out to me in a piece of code of mine I am using

char* name = malloc(256*sizeof(char));
// more code
free(name);

I was under the impression that this way of setting up an array was identical to using

char name[256];

and that both ways would require the use of free(). Am I wrong and if so could someone please explain in low level terms what the difference is?

+2  A: 

This is incorrect - the array declaration does not require a free. Further, if this is within a function, it is allocated on the stack (if memory serves) and is automatically released with the function returns - don't pass a reference to it back the caller!

Software Monkey
+21  A: 

In the first code, the memory is dynamically allocated on the heap. That memory needs to be freed with free(). Its lifetime is arbitrary: it can cross function boundaries, etc.

In the second code, the 256 bytes are allocated on the stack, and are automatically reclaimed when the function returns (or at program termination if it is outside all functions). So you don't have to (and cannot) call free() on it. It can't leak, but it also won't live beyond the end of the function.

Choose between the two based on the requirements for the memory.

Addendum (Pax):

If I may add to this, Ned, most implementations will typically provide more heap than stack (at least by default). This won't typically matter for 256 bytes unless you're already running out of stack or doing heavily recursive stuff.

Also, sizeof(char) is always 1 according to the standard so you don't need that superfluous multiply. Even though the compiler will probably optimize it away, it makes the code ugly IMNSHO.

End addendum (Pax).

Ned Batchelder
You can also declare the memory outside all functions and it does not take up space on the stack. Again, it depends on the needed lifetime of the buffer to know what allocation is correct.
jmucchiello
Bad things happen if you use the char[] foo inside the function, and the function returns foo. Having an example of the pitfall could be nice.
Calyth
At the Addendum (Pax), I think it is good practice to include sizeof(type) when calling malloc. It is less likely someone will forget to change the allocated size if the type changes while using sizeof() instead of your implication.
strager
Another note: sizeof name in first case is 4 on most machines( size of a 32-bit pointer). sizeof name in the second case is 256 (size of array of 256 characters).
Arkadiy
+5  A: 

and that both ways would require the use of free().

No, only the first needs the use of a free. The second is allocated on the stack. That makes it incredibly fast to allocate. Look here:

void doit() {
    /* ... */
    /* SP += 10 * sizeof(int) */
    int a[10];
    /* ... (using a) */

} /* SP -= 10 */

When you create it, the compiler at compile time knows its size and will allocate the right size at the stack for it. The stack is a large chunk of continuous memory located somewhere. Putting something at the stack will just increment (or decrement depending on your platform) the stackpointer. Going out of scope will do the reverse, and your array is freed. That will happen automatically. Therefor variables created that way have automatic storage duration.

Using malloc is different. It will order some arbitrary large memory chunk (from a place called freestore). The runtime will have to lookup a reasonably large block of memory. The size can be determined at runtime, so the compiler generally cannot optimize it at compile time. Because the pointer can go out of scope, or be copied around, there is no inherent coupling between the memory allocated, and the pointer to which the memory address is assigned, so the memory is still allocated even if you have left the function long ago. You have to call free passing it the address you got from malloc manually if the time has come to do so.

Some "recent" form of C, called C99, allows you to give arrays an runtime size. I.e you are allowed to do:

void doit(int n) {
    int a[n]; // allocate n * sizeof(int) size on the stack */
}

But that feature should better be avoided if you don't have a reason to use it. One reason is that it's not failsafe: If no memory is available anymore, anything can happen. Another is that C99 is not very portable among compilers.

Johannes Schaub - litb
I'm curious... what's the relationship between the C99 feature and alloca()? I know most resources say to avoid alloca() because of the invisible/devastating failure mechanism.
Tom
The C99 feature is just a built-in alloca, with the advantage that the memory is freed for you automatically. All the same dangers are present - you have to be very careful to keep the amount of memory allocated small.
James Hopkin
there are limited uses for it. for example pcre (regular expression lib) can use it for its memory allocation instead of recursion afaik. if you don't need that speed then better use malloc or a fixed size array. most often that is what you want.
Johannes Schaub - litb
+3  A: 

There is a third possibility here, which is that the array can be declared external to a function, but statically, eg,

// file foo.c
char name[256];

int foo() {
    // do something here.
}

I was rather surprised in answers to another question on SO that someone felt this was inappropriate in C; here's it's not even mentioned, and I'm a little confused and surprised (like "what are they teaching kids in school these days?") about this.

If you use this definition, the memory is allocated statically, neither on the heap nor the stack, but in data space in the image. Thus is neither must be managed as with malloc/free, nor do you have to worry about the address being reused as you would with an auto definition.

It's useful to recall the whole "declared" vs "defined" thing here. Here's an example

/* example.c */

char buf1[256] ;           /* declared extern, defined in data space */
static char buf2[256] ;    /* declared static, defined in data space */
char * buf3 ;              /* declared extern, defined one ptr in data space */
int example(int c) {       /* c declared here, defined on stack */
    char buf4[256] ;       /* declared here, defined on stack   */
    char * buf5 = malloc(256)]   /* pointer declared here, defined on stack */
                           /* and buf4 is address of 256 bytes alloc'd on heap */
    buf3 = malloc(256);    /* now buf3 contains address of 256 more bytes on heap */

    return 0;              /* stack unwound; buf4 and buf5 lost.      */
                           /* NOTICE buf4 memory on heap still allocated */
                           /* so this leaks 256 bytes of memory */
}

Now in a whole different file

/* example2.c */

extern char buf1[];             /* gets the SAME chunk of memory as from example.c */
static char buf2[256];          /* DIFFERENT 256 char buffer than example.c */
extern char * buf3 ;            /* Same pointer as from example.c */
void undoes() {
     free(buf3);                /* this will work as long as example() called first */
     return ;
}
Charlie Martin
+2  A: 

Break down your statement

char* name = malloc(256*sizeof(char)); // one statement
char *name; // Step 1 declare pointer to character
name = malloc(256*sizeof(char)); // assign address to pointer of memory from heap
name[2]; // access 3rd item in array
*(name+2); // access 3rd item in array
name++; // move name to item 1

Translation: name is now a pointer to character which is assigned the address of some memory on the heap

char name[256]; // declare an array on the stack
name++; // error name is a constant pointer
*(name+2); // access 3rd item in array
name[2]; // access 3rd item in array
char *p = name;
p[2]; // access 3rd item in array
*(p+2); // access 3rd item in array
p++; // move p to item 1
p[0]; // item 1 in array

Translation: Name is a constant pointer to a character that points to some memory on the stack

In C arrays and pointers are the same thing more or less. Arrays are constant pointers to memory. The main difference is that when you call malloc you take your memory from the heap and any memory taken from the heap must be freed from the heap. When you declare the array with a size it is assigned memory from the stack. You can't free this memory because free is made to free memory from the heap. The memory on the stack will automatically be freed when the current program unit returns. In the second example free(p) would be an error also. p is a pointer the name array on the stack. So by freeing p you are attempting to free the memory on the stack.

This is no different from:

int n = 10;
int *p = &n;

freeing p in this case would be an error because p points to n which is a variable on the stack. Therefore p holds a memory location in the stack and cannot be freed.

int *p = (int *) malloc(sizeof(int));
*p = 10;
free(p);

in this case the free is correct because p points to a memory location on the heap which was allocated by malloc.

Cervo
Don't you mean int *p = (int *)malloc(sizeof(int));? :-)
Anthony Cuozzo
Yeah I edited the post, it has been a while since I used malloc :)
Cervo
A: 

salut j ai pas compru le codes sourcessuivant SVP expliquer moi le codes sources et qu est ce que faire

void __fastcall TForm3::DescribeTable(char * TableName { MYSQL_ROW myRow; MYSQL_RES *myRES; char q=(char) malloc(256); strcpy(q,"describe "); strcat(q,TableName);

mysql_real_query(&Connexion,q,strlen(q)); myRES = mysql_store_result(&Connexion); lsFields->ColCount = 2; lsFields->RowCount = 2; lsFields->ColWidths[0]=250; lsFields->ColWidths[1]=200; lsFields->Cells[0][0]="Field Name" ; lsFields->Cells[1][0]="Field Type(Length)" ; int i=1,j; while(1) { myRow = mysql_fetch_row(myRES); if (myRow==NULL) break; StringGrid1->RowCount =i+1; for(j=0; j < 2;j++) lsFields->Cells[j][i]=myRow[j]; i++; } mysql_free_result(myRES); }

void __fastcall TForm3::dbListClick(TObject *Sender) { if(dbList->Items->Count >= 1 ) DescribeTable(dbList->Items->Strings[dbList->ItemIndex].c_str()); }

A: 

void __fastcall TForm1::ToolButton2Click(TObject *Sender) {

char *q=(char ) malloc(80); strcpy(q,"Select "); strcat(q,ClasseField); strcat(q,",count() As Frequence from ");

strcat(q,CurrentTable); strcat(q," Group by "); strcat(q,ClasseField); pas comprer cette déclaration

A: 

depending on where you are running this, stack space might be at a HUGE premium. If, for example, you're writing BREW code for Verizon/Alltel handsets, you are generally restricted to miniscule stacks but have ever increasing heap access.

Also, as char[] are most often used for strings, it's not a bad idea to allow the string constructing method to allocate the memory it needs for the string in question, rather than hope that for ever and always 256 (or whatever number you decree) will suffice.

Dr.Dredel