variable length array memory loss durch longjump



  • Ich hab neulich durch die Spezifikation von setjmp geblättert und habe folgendes verwirrendes Beispiel unter "7.13.2.1 The longjmp function" gefunden:

    EXAMPLE The longjmp function that returns control back to the point of the setjmp invocation
    might cause memory associated with a variable length array object to be squandered.

    #include <setjmp.h>
    
    jmp_buf buf;
    void g(int n);
    void h(int n);
    int n = 6;
    
    void f(void)
    {
        int x[n]; // valid: f is not terminated
        setjmp(buf);
        g(n);
    }
    
    void g(int n)
    {
        int a[n]; // a may remain allocated
        h(n);
    }
    
    void h(int n)
    {
        int b[n]; // b may remain allocated
        longjmp(buf, 2); // might cause memory loss
    }
    

    Normalerweise nahm ich immer an, VLAs würden stets auf dem Stack angelegt, bedeutet aber nicht dieses Beispiel, dass sie auch auf dem Heap landen dürfen?
    Das macht den longjmp noch mal um einiges riskanter.

    Zweitens, da dies ja nur ein Beispiel ist, müsste das Verhalten ja irgendwo vermerkt sein, ich kann aber nichts finden, was darauf hindeuten würde:

    7.13.2 Restore calling environment
    7.13.2.1 The longjmp function
    Synopsis
    1 #include <setjmp.h>
    _Noreturn void longjmp(jmp_buf env, int val);
    Description
    2 The longjmp function restores the environment saved by the most recent invocation of
    the setjmp macro in the same invocation of the program with the corresponding
    jmp_buf argument. If there has been no such invocation, or if the invocation was from
    another thread of execution, or if the function containing the invocation of the setjmp
    macro has terminated execution in the interim, or if the invocation of the setjmp
    macro was within the scope of an identifier with variably modified type and execution has
    left that scope in the interim, the behavior is undefined.
    3 All accessible objects have values, and all other components of the abstract machine
    have state, as of the time the longjmp function was called, except that the values of
    objects of automatic storage duration that are local to the function containing the
    invocation of the corresponding setjmp macro that do not have volatile-qualified type
    and have been changed between the setjmp invocation and longjmp call are
    indeterminate.
    Returns
    4 After longjmp is completed, thread execution continues as if the corresponding
    invocation of the setjmp macro had just returned the value specified by val. The
    longjmp function cannot cause the setjmp macro to return the value 0; if val is 0,
    the setjmp macro returns the value 1.

    Bin ich blind?



  • VLAs können auch auf dem Heap allociert werden, denn sie sollen nur beim verlassen des Scopes deallociert werden.
    Da könnte man also auch einach Heap-Allokations-Code (malloc/free o.ä.) generieren.
    Aber bei einem longjmp wird einfach ein "enviroment" wiederhergestellt, wobei das Verlassen der "übersprungenen" Scopes nicht stattfindet muss (anders als z.B. bei C++ Exceptions wo alle "übersprungenen" Scopes normal verlassen werden).
    So kann es passieren, dass bei einem longjmp die VLAs der "übersprungenen" Scopes nicht freigegen werden.

    Die VLA implementierung von Cray hat oder hatte dieses Problem.(3.5.8, http://docs.cray.com/books/004-2179-001/html-004-2179-001/z893434830malz.html)

    Die meisten Implementierungen allokieren VLAs auf dem Stack. Manche benutzen dafür alloca, welches eine etwas andere Semantik hat (deallocation beim verlassen der Funktion nicht des Scopes).(Vorsicht VLAs und alloca in einer Funktion mischen ist keine gute Idee)

    Wenn du setjmp und longjmp benutzt, schau dir auch sigsetjmp siglongjmp an.



  • Okey danke, wollte nur sehen ob ich das richtig verstanden habe.


Log in to reply