Stories
Slash Boxes
Comments

SoylentNews is people

posted by chromas on Monday October 29 2018, @11:05AM   Printer-friendly
from the constants-aren't-variables-won't dept.

https://www.phoronix.com/scan.php?page=news_item&px=Linux-Kills-The-VLA:

VLAs [(Varable Length Arrays)] allow for array lengths to be determined at run-time rather than compile time. The Linux kernel has long relied upon VLAs in different parts of the kernel -- including within structures -- but going on for months now (and years if counting the kernel Clang'ing efforts) has been to remove the usage of variable-length arrays within the kernel. The problems with them are:

- Using variable-length arrays can add some minor run-time overhead to the code due to needing to determine the size of the array at run-time.

- VLAs within structures is not supported by the LLVM Clang compiler and thus an issue for those wanting to build the kernel outside of GCC, Clang only supports the C99-style VLAs.

- Arguably most importantly is there can be security implications from VLAs around the kernel's stack usage.

[...] Kees Cook[*] sent out the pull request today for VLA removal that now enables the "-Wvla" compiler flag to emit a warning should any variable-length array be found within the kernel's C code. That will help prevent new code from inadvertently using VLAs and also spot any lingering kernel code still relying upon this behavior.

Kees Cook wrote that there still might be a few places where VLAs could be found, "there may be a couple more VLAs hiding in hard-to-find randconfigs, but nothing big has shaken out in the last month or so in linux-next. We should be basically VLA-free now! Wheee. :)"

[*] KeesCook.

Have you ever used VLAs? Removed them? Why?


Original Submission

 
This discussion has been archived. No new comments can be posted.
Display Options Threshold/Breakthrough Mark All as Read Mark All as Unread
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
  • (Score: 0) by Anonymous Coward on Monday October 29 2018, @03:05PM (2 children)

    by Anonymous Coward on Monday October 29 2018, @03:05PM (#755126)

    Use one of these:

    int *my_array = malloc(10 * sizeof *my_array);
    int *my_array = malloc(10*sizeof *my_array);

    In this case though, it's more like:

    int *my_array[array_size]; // array_size is a function arg

  • (Score: 4, Informative) by pe1rxq on Monday October 29 2018, @03:52PM

    by pe1rxq (844) on Monday October 29 2018, @03:52PM (#755148) Homepage

    Not precise.....
    You now ended up with a variable lenght array of integer pointers instead of integers...

    Different example:
    void foo_with_alloc(size_t array_size)
    {
          int *my_array = malloc(sizeof(int) * array_size);

          /* do foo */

          free(my_array);
    }

    And replace it with:
    void foo_with_vla(size_t array_size)
    {
          int my_array[array_size];

        /* do foo */
    }

    The differences are that malloc uses heap while vla uses the stack.
    The big danger with the malloc version is that you forget the free at the end (or any other 'ends' if foo has multiple exit points)
    The big danger with the vla version is that your stack can get really big if you don't know what you are doing.

  • (Score: 3, Informative) by Immerman on Monday October 29 2018, @05:06PM

    by Immerman (3985) on Monday October 29 2018, @05:06PM (#755199)

    The functionality would be pretty much the same, but the I suspect the in-memory structures would be very different, which can have profound performance implications in some situations. (I'm not actually familiar with using VLAs, but given their syntax and the language rules I only see one obvious candidate)

    The key factor is that
    int x;
    int vla_array[size];
    int z;
    Guarantees that the contents of vla_array lie in the immediately vicinity of x and z, dramatically increasing the chances that they'll all be loaded into processor cache at the same time after not having been accessed recently.

    Whereas
    int x;
    int *heap_array = malloc(..size..);
    int z;
    Means that the contents of heap_array are located at an effectively random location in memory. Which means that once all the data has left the cache, and then you say "....the_array[7]...."; You trigger a cache-miss to load the pointer "heap_array" and then, once that's fully loaded, immediately trigger *another* cache-miss to load the contents of the array. And triggering a cache-miss is one of the most performance-killing things you can do. Depending on expected access patterns, the difference can have a devastating effect on performance.

    There's also a smaller but more persistent performance penalty in that
    vla_array[3] translates to "dereference(3 + offset_to_vla_array + stack_pointer )"
    heap_array[3] translates to "dereference( 3 + dereference(stack_pointer + offset_to_heap_array_pointer)) "
    with the performance cost of dereferencing being dependent on hardware, compiler, and code characteristics.

    And as alluded above me - allocating and deallocating memory on the stack is essentially free, while doing so on the heap can incur a substantial penalty - both in immediate costs and in memory fragmentation.

    There's also situations where in-place arrays would be just as bad for performance - the key is to understand what you're actually asking of the computer so that you can use the right tool for the job.