VAR_INST Heap oder Stack?

2017-10-28
2017-10-29
  • schnasseldag - 2017-10-28

    Hallo miteinander,

    https://help.codesys.com/webapp/cds-vartypes-var-inst;product=codesys;version=3.5.11.0

    Oder andersherum gefragt - wie kommt der Funktionsbaustein an einen Stack? Das kann er doch nur über eine Task, sprich, wenn eine (z.B. globale) Funktion eine lokale Instanz (also auf dem Stack des aufrufenden Threads) einer Klasse erzeugt, die dann eine (Member-) Funktion enthält, welche Ihrerseits eine VAR_INST-Deklaration beinhaltet. Nur in diesem Fall läge die VAR_INST Variable dann tatsächlich auf einem Stack (des aufrufenden Thread/der aufrufenden Task)?!

    Kann mir hier jemand auf die Sprünge helfen?

    PS: Ich komme aus der C/C++ Ecke und tue mich mit solchen Termini leichter

    Schöne Grüße

    schnasseldag

     
  • schnasseldag - 2017-10-29

    Mittels eines kleinen Beispiels habe ich mir die Frage nun selbst beantwortet.

    VAR_INST deklarierte Variable teilen sich den Speicherbereich mit den (Member-) Variablen der Objektinstanz (innerhalb derer die (Member-) Funktion deklariert ist). Von Ihrer Sichtbarkeit (Scope) her sind sie jedoch auf die der (Member-) Funktion beschränkt. Deklarieren mehrere (Member-) Funktionen Variablen desselben Namens, so werden für jede Variablendeklaration auch einzelne Speicherbereiche in der Objektinstanz erzeugt (vermutlich durch das Namemangling des Compilers).

    Überprüft habe ich dies durch einen Wertevergleich einer echten Stackvariable (VAR_INPUT innerhalb einer Funktion ) und einer VAR_INST-Variable nach einigen rekursiven Aufrufen der Funktion . Währenddessen die Stackvariable für jeden Funktionsaufruf einen anderen Wert besitzt, wird die VAR_INST Variable (weil "global" in der Objekinstanz) immer wieder überschrieben. Anbei der Code:

    METHOD PUBLIC foo : INT
    VAR_INPUT
       count : INT;
    END_VAR
    VAR_INST
       test_count : INT := 0;   
    END_VAR
    test_count := count;
    IF (count > 0) THEN
       THIS^.foo(count - 1);
    END_IF
    IF (count = test_count) AND (count > 0) THEN
       bIsStackVariable := TRUE; // test_count ist eine Stack-Variable
       ELSE
          bIsStackVariable := FALSE; // test_count ist eine Objekt-Variable
       END_IF
    // Was liefert uns nun test_count_count der Funktion foo2()?
    foo := foo2();
    // foo2() liefert immer 42 für deren test_count Variable zurück. 
    // Damit wird in der FB1-Instanz offenbar eine weitere Speicherstelle allociert. 
    // Vom Compiler scheint das wohl per Namemangling der Art "FB_foo_test_count" bzw."FB_foo2_test_count" o.ä. gelöst zu sein?!  
    

    liefert brav 42 zurück. Deren Variable "kollidiert" also nicht mit der aus der Funktion .

    METHOD PUBLIC foo2 : INT
    VAR_INST
       test_count : INT := 42;   
    END_VAR
    // Greifen foo2() und foo() auf die gleiche Variable innerhalb des FB1 zu?
    foo2 := test_count;
    // Antwort: Nein. Der Compiler erzeugt für beide lokalen Variablen einen eigenen Speicherbereich im FB1-Objekt.
    

    Im Anhang befindet sich der vollständige Testcode.

    VarInst.zip [375.75 KiB]

     

Log in to post a comment.