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) |
Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - Zum C-Control-I-Forum - Zum C-Control-II-Forum