OK folks, corrected

Discussion in 'C Programming' started by jacob navia, Mar 7, 2008.

  1. jacob navia

    jacob navia Guest

    After a heated discussion, I decided to fix this problem of VLAs
    It took me almost the whole day to realize that

    1) I am storing the size of ALL VLAs in a hidden local variable
    in case somebody calls sizeof(vla), and I need to return that
    size. This means most of this problem was solved already.

    2) I am executing code anyway when I leave a scope.


    When leaving a scope with level bigger than function, i.e. an inner
    scope, go through all local variables of that scope and see if it
    is a VLA.

    If it is, look where its size is stored. Read that size and add it to
    the stack pointer.


    Open questions:
    What happens with:

    for (int i = 0; i<100; i++) {
    int tab[i*1024];
    int *pint = alloca(42);

    With the current scheme of freeing the VLAs this
    will crash.


    This was NOT crashing before. I do not know what to do with
    this stuff.

    gcc dedicates a register to save the stack position
    in such blocks. When the block exits, the whole stack
    is restored, what means that the alloca's done are
    automatically taken care of correctly.

    This is a hell of expensive, since I have only 3 free registers in
    the x86 32 bit architecture. This means that I would lose 33% of the
    machine dedicated to holding the stack value.

    gcc uses esi, and it can (with its bloated "optimize it all"
    machinery) remark that this is only used in this block and
    can be used elsewhere. I do not do global register allocation,
    since it just would bring me a few percent speed gain at enormous

    I would have to dedicate the register within the WHOLE function.

    For the time being I will leave it like this. Note that using
    alloca within a loop is quite suicidal anyway, since all the storage
    can't be reclaimed until the function exit in principle in many

    I can "cheat out" by writing this in the docs...

    "Do not use alloca in blocks using VLAs"


    So, I see the regulars come and start arguing:

    "Jacob recommended alloca and it crashes. "
    jacob navia, Mar 7, 2008
    1. Advertisements

  2. jacob navia

    santosh Guest

    Can't you use a normal variable instead of a register?

    santosh, Mar 7, 2008
    1. Advertisements

  3. jacob navia

    jacob navia Guest

    Not easily. I know the size of the VLA expression because I store
    it in a variable.

    With alloca however, I would have to modfy the
    signature of alloca to make a new alloca

    void *new_alloca(size_t siz, size_t *pVar);

    and alloca would store in pVar the size of the variable
    it allocates, adding it in case there are two or more

    This would imply that I monitor all calls and see if they
    are a call to "alloca", and if they are, I pass the
    address of that variable (that must be block specific)

    Obviously, I would spare myself all the adds to esp
    and I could do it in a single instruction like
    move %esi,%esp


    in the x86 is quite expensive.

    In x86-64 this is the way to go since there are 8 more
    registers, and dedicating one is much less expensive anyway.

    In the power pc lcc-win this is not even a problem with 32 registers!
    jacob navia, Mar 7, 2008
  4. jacob navia

    CBFalconer Guest

    You have a much easier and more accurate solution available.
    Document that:

    "alloca is not provided, because it is not described in
    the C standard, and the requirement is handled by VLAs."
    CBFalconer, Mar 7, 2008
  5. That's why you shouldn't be recommending that people use alloca(). :)
    That would be my suggestion. Another alternative would be to set a flag
    in the compiler when you see alloca() in a block and then revert to the
    previous behavior where you don't adjust the stack pointer at the end of
    the block.

    -Larry Jones

    Years from now when I'm successful and happy, ...and he's in
    prison... I hope I'm not too mature to gloat. -- Calvin
    lawrence.jones, Mar 7, 2008
  6. jacob navia

    Willem Guest

    jacob wrote:
    ) Open questions:
    ) --------------
    ) What happens with:
    ) for (int i = 0; i<100; i++) {
    ) int tab[i*1024];
    ) int *pint = alloca(42);
    ) }

    I just tested this on gcc-4.1.3 and it looks like the alloca()'d blocks
    are freed as soon as the block is left. Not what the manpage states.

    #include <stdio.h>
    #include <alloca.h>

    int main(void)
    int i, n;
    int *ptr[10];
    n = 10;
    for (i = 0; i < 10; i++) {
    int tab[n];
    ptr = alloca(1);
    for (i = 0; i < 10; i++) {
    fprintf(stderr, "%d: %p\n", i, (void *)ptr);
    return 0;


    0: 0xbf8799e0
    1: 0xbf8799e0
    2: 0xbf8799e0
    3: 0xbf8799e0
    4: 0xbf8799e0
    5: 0xbf8799e0
    6: 0xbf8799e0
    7: 0xbf8799e0
    8: 0xbf8799e0
    9: 0xbf8799e0

    NB: This only happens in the presence of a VLA.
    If you comment out the VLA, the pointers are different.

    SaSW, Willem
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    Willem, Mar 7, 2008
  7. jacob navia

    Ben Pfaff Guest

    How about adding a diagnostic so that people who don't read the
    docs get some help too?
    Ben Pfaff, Mar 7, 2008
  8. Good for you.

    [big snip]
    Not an unreasonable solution. If you feel you must support alloca(),
    it's good to emphasize how fragile it is. Anyone using it must read
    the implementation's documentation carefully to see how its use is
    We don't need to make that argument. You've made it for us quite

    Now that this issue is settled, please take a moment to consider that
    we were right, and you were wrong, all along. Everyone is wrong
    sometimes, but consider not responding to all criticism (and all bug
    reports from people you dislike) as personal attacks.

    This post is intended as *constructive* criticism. I'll be pleasantly
    surprised if you take it that way. I truly don't enjoy watching you
    act like a paranoid fool.
    Keith Thompson, Mar 7, 2008
  9. I havent seen the VLA discussion, but why would anyone want to use alloca
    and VLA's at the same time?

    Or does it crash too when you have a VLA and call a function that uses
    Serve Laurijssen, Mar 7, 2008
  10. jacob navia

    user923005 Guest

    The fact that he recognized a problem, repaired it, and reported the
    correction is certainly encouraging. As long as people show me that
    they are actually listening to dialogue (even if they drag their feet,
    kicking and screaming during the dialog), there is no reason to stop
    reading them. So Jacob will never go into my category for people like
    'Kenny' and 'Twink' who are simply contrary for the sake of being
    user923005, Mar 7, 2008
  11. jacob navia

    Ian Collins Guest

    That's good to hear. It's a pity not all compiler vendors respond so
    Drop alloca in favour of VLAs. Or implement alloca as a wrapper over a VLA.
    Ian Collins, Mar 7, 2008
  12. jacob navia

    jacob navia Guest

    No, that is not possible anyway since a function when leaving
    will erase any alloca allocations
    jacob navia, Mar 7, 2008
  13. No. We're not!
    Kenny McCormack, Mar 7, 2008
  14. The former would break any existing code that uses alloca (which I'm
    not entirely convinced would be a bad thing). The latter doesn't
    satisfy the required semantics of alloca; if you call alloca N times
    in a loop, all N allocated objects continue to exist until the
    function terminates.
    Keith Thompson, Mar 8, 2008
  15. jacob navia

    Ian Collins Guest

    How can a non-standard function have defined semantics?
    Ian Collins, Mar 8, 2008
  16. Well then the only time I can think of that somebody uses alloca and VLA's
    at the same time is when a macro is used that uses VLA's or alloca and the
    programmer forgot that.
    A reminder by the compiler would be very handy :) It could save loads of
    debugging time
    Serve Laurijssen, Mar 8, 2008
  17. The same way malloc() had defined semantics before 1989.

    Every alloc() man page I've seen says the allocated memory is freed
    when the calling function returns. If an implementation wants to
    provide a (non-standard) function that doesn't behave that way, it
    shouldn't call it "alloca".
    Keith Thompson, Mar 8, 2008
  18. Ian Collins said:

    By making it the fourth argument in a qsort call? :)
    Richard Heathfield, Mar 8, 2008
  19. jacob navia

    santosh Guest

    Doesn't that constitute as just defining the interface?
    santosh, Mar 8, 2008
  20. "The function shall return an integer less than, equal to, or greater than
    zero if the first argument is considered to be respectively less than,
    equal to, or greater than the second."

    Unrelated to the actual topic, but a question about qsort: is the
    behaviour defined if compar longjmps out of qsort when the two arguments
    are considered incomparable by the application? It needs some way to exit
    without returning an integer. :)
    Harald van Dijk, Mar 8, 2008
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.