Defining a temporary array on stack

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Defining a temporary array on stack

Jump to solution
3,050 Views
mjbcswitzerland
Specialist V
Hi All
 
I just had a problem with CW4.5 for HC(S)12. It started me thinking - I wonder whether any one knows the answer:
 
1. I had a project which was working when compiled with other compilers but would work strangely when compiled with CW. It would crash when a certain routine was called and did something strange when another routine was called.

2. I realised that both issues were either present, or could be corrected, by writing static arrays differently, as follows:
 
Method 1:
unsigned char tx_message[ HEADER_LENGTH ] = { INTERNAL_ROUTE, INTERNAL_ROUTE , tcp_tx->cWakeTask, INTERRUPT_EVENT, TX_FREE };
 
This doesn't work with CW when it is used within a conditional statement in a routine (but I think is OK when used on entry to a routine) and causes strange behaviour.
 
Method 2:
               unsigned char tx_message[ HEADER_LENGTH ];
               tx_continue_message[ 0 ] = INTERNAL_ROUTE;
               tx_continue_message[ 1 ] = INTERNAL_ROUTE;
               tx_continue_message[ 2 ] = tcp_tx->cWakeTask;
               tx_continue_message[ 3 ] = INTERRUPT_EVENT;
               tx_continue_message[ 4 ] = TX_FREE;
 
This construct works fine with CW. The code runs perfectly.
3. I was not getting any warnings (from none of the compilers I use) about this type of construct, therefore my question - is it a non-standard construct which I shouldn't really be using ? Or is it a CW bug?
 
4. I actually prefer the first method since it allows setting the array without defining its length and I think that it is easier to make a mistake when coding using the second method. I was however surprised to find out that when I checked the code efficience (using GNU compiler as reference - which doesn't mean it is the same for all) the second method was actually being coded with only about 50% of the code size - so I have used the same construct in all code now.....Just a note..
 
Any one have comments?
 
Regards
 
Mark Butcher
www.mjbc.ch
 
 
Labels (1)
Tags (1)
0 Kudos
Reply
1 Solution
867 Views
CrasyCat
Specialist III

Hello

If you feel it is an compiler error, please submit a service request through our on line support web page.

Use following URL:
http://www.freescale.com/webapp/sps/site/homepage.jsp?nodeId=054670&tid=FSH
then click on "Submit a service Request".

Make sure you attach a reproducible case and indicate which version of the tools you are using and which compiler options you are using.

CrasyCat

View solution in original post

0 Kudos
Reply
3 Replies
867 Views
CrasyCat
Specialist III

Hello

I would need more information to find out what is going on here.

1- Not sure on what is happening here. You tell that you have array on the stack. Make sure to define a stack with an appropriate size. You may be facing a stack overflow issue. Defining a local variable as static is in fact the same as defining a global variable.
If the application is working then, I would highly suspect a stack overflow.

Also if you define a local array variable, you have to make sure the variable is initialized in the function. You cannot assume the variable is initialized with 0 at the beginning of the function. Here again, defining the variable as static will ensure the startup code will initialize it with 0. Which is not the case for local variables.

2- Is the table tx_message static or not? Local or not?
Initialization value for local static variables is evaluated at compile time.
The value of tcp_tx->cWakeTask is not known at compile time, so the compiler will generate an error.

CrasyCat

0 Kudos
Reply
867 Views
mjbcswitzerland
Specialist V

Hi CrasyCat

The declaration is not for a static array as such (with static definition) but is created for a short time on the stack by the compiler (probably it is called local). When I use a static definition the generated code is different and of course the values in the array must be fixed.

I am very sure that it is not a stack overflow for a number or reasons:
1. The operating system has a stack monitor and says that there has been no overflow.
2. The size of the array is the same, which ever method is used. In fact it is not possible to overwrite the end of the array using the first method since the compiler will catch it (usually also using the second method).
3. The same code runs fine when compiled with GNU, IAR or VisualStudio compilers. It runs on HCS12, ARM and a few other platforms.

 

I did a quick test:

The array on stack which I expect is
0,0, variable value, 0xff, 0xdc (4 from the 5 bytes are fixed values)


The following code is generated using the second method (when each array entry is written into the array):
 012d 69f012       [3]     CLR   18,SP    ; 0 to array[0]
 0130 69f013       [3]     CLR   19,SP    ; 0 to array[1]
 0133 6bf014       [3]     STAB  20,SP   ; variable value (obviously in B) to array[2]
 0136 ccdcff       [2]     LDD   #56575  ; load 0xdcff to D
 0139 6bf015       [3]     STAB  21,SP  ; 0xff to array[3]
 013c 6af016       [3]     STAA  22,SP  ; 0xdc to array[4]

All looks fine

The following code is generated using the first method (when the array and its contents are defined on one line)

 012f 69f012       [3]     CLR   18,SP     ; 0 to array[0]
 0132 69f013       [3]     CLR   19,SP    ; 0 to array[1]
 0135 ccdcff       [2]     LDD   #56575   ; load 0xdcff to D
 0138 6bf015       [3]     STAB  21,SP   ; 0xff to array[3]
 013b 6af016       [3]     STAA  22,SP   ; 0xdc to array[4]
 013e 1a8e         [2]     LEAX  14,SP    ; get an address?
 0140 6ef014       [3]     STX   20,SP   ;; store address in array[2] and array[3]?

My feeling is that something is going wrong with the last two assembler instructions. It seems (I don't work a lot with assembler...) that an address is being loaded into X and then X is being written to the third location in the array, and overwriting also the 4th position (STX stores the 16 bit contents of X in 2 bytes of memory).

So my feeling is stronger now that this is a compiler issue (I tested with CW3.1 and 4.5).

To be sure that the context of the code is clear, here is the original in full (method 1):

... in routine

       if (DataCopied == 0) {
           if (tcp_tx->cWakeTask ) {
               unsigned char tx_message[ HEADER_LENGTH ] = { INTERNAL_ROUTE, INTERNAL_ROUTE, tcp_tx->cWakeTask, INTERRUPT_EVENT, TX_FREE};        

               fnWrite( INTERNAL_ROUTE, tx_message, HEADER_LENGTH); // Inform the blocked task
           }
       }

... continue routine

The issue is definitely resolved by using method 2 as below

... in routine

       if (DataCopied == 0) {
           if (tcp_tx->cWakeTask ) {
               unsigned char tx_message[ HEADER_LENGTH ];
               tx_continue_message[ 0 ] = INTERNAL_ROUTE;
               tx_continue_message[ 1 ] = INTERNAL_ROUTE;
               tx_continue_message[ 2 ] = tcp_tx->cWakeTask;
               tx_continue_message[ 3 ] = INTERRUPT_EVENT;
               tx_continue_message[ 4 ] = TX_FREE;

               fnWrite( INTERNAL_ROUTE, tx_message, HEADER_LENGTH); // Inform the blocked task
           }
       }

... continue routine

 

Interesting stuff but can loose quite a lot of time with such issues (one reason why I do projects with several compilers at the same time - I know of no cross-C-compiler which doesn't have bugs. The VisualStudio compiler is possibly the ultimative reference but it is not a cross compiler so can only be used a igh level reference...

Regards

Mark Butcher
www.mjbc.ch

 

0 Kudos
Reply
868 Views
CrasyCat
Specialist III

Hello

If you feel it is an compiler error, please submit a service request through our on line support web page.

Use following URL:
http://www.freescale.com/webapp/sps/site/homepage.jsp?nodeId=054670&tid=FSH
then click on "Submit a service Request".

Make sure you attach a reproducible case and indicate which version of the tools you are using and which compiler options you are using.

CrasyCat

0 Kudos
Reply