Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm using the following code in my application, and it's working fine. But I'm wondering if it's better to make it with malloc or to leave it as is?

function (int len)
{
char result [len] = some chars;
send result over network
}
share|improve this question
1  
Is the assumption that the code is targeted for a non-embedded environement? –  tehnyit May 8 '12 at 12:14

7 Answers 7

Variable-length automatic arrays were introduced to C in C99.

Unless you have concerns about backwards comparability to older standards, it's fine.

In general, if it works, don't touch it. Don't optimize ahead of time. Don't worry about adding special features or clever ways of doing things, because you often aren't going to use it. Keep it simple.

share|improve this answer
3  
I have to disagree with the "if it works, don't touch it" dictum. Falsely believing that some code "works" can cause you to work around problems in some code that "works". Belief must be replaced by tentative acceptance that some code works right now. –  Bruce Ediger Apr 11 '12 at 15:39
2  
Don't touch it until you make a version maybe "works" better... –  H_7 Apr 11 '12 at 22:57

If your compiler supports variable-length arrays, the only danger is overflowing the stack on some systems, when the len is ridiculously large. If you know for sure that len is not going to be larger than a certain number, and you know that your stack is not going to overflow even at the max length, leave the code as is; otherwise, rewrite it with malloc and free.

share|improve this answer
    
what about this on non c99 function (char[]) { char result [sizeof(char)] = some chars; send result over network } –  Dev Bag Apr 10 '12 at 21:30
    
@DevBag char result [sizeof(char)] is an array of size 1 (because sizeof(char) equals one), so the assignment is going to truncate some chars. –  dasblinkenlight Apr 10 '12 at 21:33
    
sorry about that, I mean it this way function (char str[]) { char result [sizeof(str)] = some chars; send result over network } –  Dev Bag Apr 10 '12 at 21:36
3  
@DevBag This is not going to work either - str decays to a pointer, so its sizeof is going to be four or eight, depending on the pointer size on your system. –  dasblinkenlight Apr 10 '12 at 21:40
1  
If you are using a version of C without variable length arrays, you may be able to do char* result = alloca(len);, which allocates on the stack. It has the same basic effect (and same basic problems) –  Steven Burnap May 8 '12 at 15:42

The main difference is that VLAs (variable length arrays) provide no mechanism for detecting allocation failures.

If you declare

char result[len];

and len exceeds the amount of available stack space, your program's behavior is undefined. There is no language mechanism either for determining in advance whether the allocation will succeed, or for determining after the fact whether it succeeded.

On the other hand, if you write:

char *result = malloc(len);
if (result == NULL) {
    /* allocation failed, abort or take corrective action */
}

then you can handle failures gracefully, or at least guarantee that your program won't try to continue to execute after a failure.

(Well, mostly. On Linux systems, malloc() can allocate a chunk of address space even if there's no corresponding storage available; later attempts to use that space can invoke the OOM Killer. But checking for malloc() failure is still good practice.)

Another issue, on many systems, is that there's more space (possibly a lot more space) available for malloc() than for automatic objects like VLAs.

And as Philip's answer already mentioned, VLAs were added in C99 (Microsoft in particular doesn't support them).

share|improve this answer

Generally speaking the stack is the easiest and best place to put your data.

I would avoid the problems of VLAs by simply allocating the largest array you expect.

There are however there are cases when the heap is best and messing around with malloc is worth the effort.

  1. When its large but variable amount of data. Large depends on your environment > 1K for embedded systems, > 10MB for a Enterprise server.
  2. When you want the data to persist after you exit your routine, e.g. if you return a pointer to your data. Using
  3. A combination of static pointer and malloc() is usually better than defining a large static array;
share|improve this answer

Something that nobody has mentioned yet is that the variable length array option is probably going to be vastly faster than malloc/free since allocating a VLA is just a case of adjusting the stack pointer (in GCC at least).

So, if this function is one that is called frequently (which you will, of course, determine by profiling), the VLA is a good optimisation option.

share|improve this answer
    
It will seem good up until the point when it pushes you into an out-of-stack-space situation. What's more, it might not be your code that actually hits the stack limit; it could end up biting in a library or system call (or interrupt). –  Donal Fellows May 8 '12 at 12:46
    
@Donal Performance is always a trade off of memory against speed. If you are going to go round allocating arrays of several megabytes, then you have a point, however, even for a few kilobytes, as long as the function isn't recursive, it's a good optimisation. –  JeremyP May 9 '12 at 9:26

I like the idea that you can have a run-time allocated array without memory fragmentation, dangling pointers, etc. However, others have pointed out that this run-time allocation can silently fail. So I tried this using gcc 4.5.3 in a Cygwin bash environment:

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

void testit (unsigned long len)
{
    char result [len*2];
    char marker[100];

    memset(marker, 0, sizeof(marker));
    printf("result's size: %lu\n", sizeof(result));
    strcpy(result, "this is a test that should overflow if no allocation");
    printf("marker's contents: '%s'\n", marker);
}

int main(int argc, char *argv[])
{
    testit(100);
    testit((unsigned long)-1);  // probably too big
}

The output was:

$ ./a.exe
result's size: 200
marker's contents: ''
result's size: 4294967294
marker's contents: 'should overflow if no allocation'

The overly large length passed in the second call clearly caused the failure (overflowing into marker[]). This doesn't mean that this kind of check is fool-proof (fools can be clever!) or that it meets the standards of C99, but it might help if you have that concern.

As usual, YMMV.

share|improve this answer
    
+1 this is very useful :3 –  Kokizzu Jan 15 at 6:45

In embedded programming, we always use static array instead of malloc when the malloc and free operations are frequent. Because of the lack of memory management in embedded system, the frequent alloc and free operations will cause memory fragment. But we should utilize some tricky methods such as defining the max size of array and using static local array.

If your application is running in Linux or Windows, it is no matter using array or malloc. The key point lies in where you use your date structure and your code logic.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.