Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - Zum C-Control-I-Forum - Zum C-Control-II-Forum

Preprocessor Kategorie: Programmierung C (von Friedhelm Michel - 11.01.2010 14:27)


Hallo,
Ich glaube, dass ich einem unschönen Verhalten des C-Preprocessors auf die Spur gekommen bin.
Mit einer bestimmten Definitionsform einer Konstanten kann der Programm Stack während der
Laufzeit zerstört werden. Im nachfolgenden Quelltext wird die Konstannte 'DIMENSION' aus
TEST_CONST_A + TEST_CONST_B vom Preprocessor errechnet und ein Array damit dimensioniert.

Wird DIMENSION mit

 #define DIMENSION TEST_CONST_A + TEST_CONST_B

definiert dann läuft alles normal.

Wird aber folgende geklammerte Form verwendet:

 #define DIMENSION (TEST_CONST_A + TEST_CONST_B)

dann wächst der Programmstack mit jedem Unterprogrammaufruf unaufhörlich bis zum Absturz.
Das Programm verwendet ein kleines Assemblermodul um den Programm Stack und den Parameter
Stack nach jedem Unterprogrammaufruf auszulesen und anzuzeigen. Ich glaube, dass ein
Zusammenhang zwischen Konstantendefinition, Array und Unterprogrammaufruf besteht. Da mir der
Aufbau des Byteinterprteters nicht bekannt ist, kann ich leider nur das Symptom beschreiben.
Allerdings liegt die Vermutung nahe, dass die geklammerte Version als Prozedurkopf interpretiert wird.
Vielleicht kann sich einer der C-Interpreter Autoren des Fehlers annehmen. Die nicht zu verwendende
Klammerung birgt Gefahren bei der Verwendung von Preprocessor Artithmetik (Operatoren Priorität).
Das Programm erzeugt im Loop einen Unterprogrammaufruf sobald SW1 auf dem Experimentierboard
gedrĂĽckt wird. Die Stackadressen werden dazu im Output Window angezeigt.

Mit freundlichem Gruss,
Friedhelm Michel

void getCriticalSection $asm("tag1")(void);  // the assembler module declaration

unsigned int StackPointer;                // this will contain the stack addresses after each subroutine call
unsigned int ParameterStack;

#define TEST_CONST_A 8
#define TEST_CONST_B 9
#define DIMENSION TEST_CONST_A + TEST_CONST_B // the critical definition if defined in brackets

byte TestArray[DIMENSION];


void Outs(void)                         // the test subroutine
{
  ;
}

void main(void)
{
    unsigned int dimension;      // used to show the calculated array dimension
    int flag;                              // used for the current key status
    byte key;                           // the port result from SW1
    char Report[100];               // this will be the report message

    flag = 0;                                                    // initiate the key flag
    Port_DataDirBit(PORT_SW1,0);                  // we will use SW1 to trigger one loop
    Port_DataDirBit(PORT_LED1,PORT_OUT);  // the LED will be used as feedback for a pressed key

    getCriticalSection();                                   // (ASM) get the stack pointer and the parameter stack
                                                                   // to the global variables
    Str_Printf(Report,
                   "normal Stack Pointer: %drnormal Parameter Stack: %dr",
                  StackPointer,
                  ParameterStack);
    Msg_WriteText(Report);                             // and show it

    dimension = DIMENSION;                         // store, what the pre processor has calculated
    Str_Printf(Report,"Array Dimension: %dr",dimension);
    Msg_WriteText(Report);                            // and show it

    while(true)
    {
        key = Port_ReadBit(PORT_SW1);         // check the switch position of SW1
        if(key)                                                 // if it is hold down
        {
            Port_WriteBit(PORT_LED1,PORT_ON);  // indicate it with the LED off
            if(flag == 0)                                     // if the flag was zero then we observe a key state change
            {                                                    // to 'down'

                Outs();                                      // this call becomes critical if the constant DIMENSION
                                                                // is defined with brackets
                getCriticalSection();                   // (ASM get the stack pointer and the parameter stack
                                                               // to the global variables
                Str_Printf(Report,
                               "Stack Pointer: %drParameter Stack: %dr",
                              StackPointer,
                              ParameterStack);
                Msg_WriteText(Report);            // and show it
            }
            flag = 1;                                       // status is 'key down' now
        }
        else                                                // do nothing
        {
            flag = 0;                                      // but store the status
            Port_WriteBit(PORT_LED1,PORT_OFF);
        }
    }
}

; Assembler Source

.ifdef tag1

getCriticalSection:
    MOVW R26,R8                        ; get Ram Top from register 8,9
    SUBI R26,LOW(StackPointer)   ; subtract index from StackPointer to get the address
    SBCI R27,HIGH(StackPointer)
    MOVW R30,R6                        ; copy stack pointer from R6 to Z
    ST X+,R30                               ; and store it into StackPointer
    ST X,R31
    MOVW R26,R8                       ; get Ram Top from register 8,9 again
    SUBI R26,LOW(ParameterStack)   ; subtract index from ParameterStack to get the address
    SBCI R27,HIGH(ParameterStack)
    MOVW R30,R10                    ;  copy parameter stack pointer to Z
    ST X+,R30                             ; and store it into StackPointer
    ST X,R31
    ret

.endif


    Antwort schreiben


Antworten:

Re: Preprocessor (von PeterS - 12.01.2010 8:31)