Memory overlapping !!!

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

Memory overlapping !!!

4,318 Views
stephane
Contributor I
Hi there,
 
I've seen twice a memory overlap made by the compiler/linker, without warning... The second one is critical as I don't find a workaround for that
 
I'm using both CW3.1 and CW5.9
 
1. First bug
---------------
I'm setting an array at a specified memory adress like that :
 
Code:
char u8CopyRamToFlash [FLASH_PAGE_SIZE] @0x000000CB = {0};

 I'm using a HC08QB8 and if there is no RAM left, then the linker put variables inside the u8CopyRamToFlash  array without warning
 
Workaround : check al lthe time that there is no overlapping due to RAM size limitation
 
 
 
 
2. Second bug : critical no workaround found
----------------------------------------------------------
I'm using then HCS08AW.
I've the folowing code :

 
Code:
void GLCD_Printf (char *au8Text, FONT_DEF *stFont, char u8Type) { while(*au8Text != 0) {  LcdPutchar (*au8Text, stFont, u8Type);  au8Text++; }}void LcdPutchar (char u8Char, FONT_DEF *stFont, char u8Type){ char u8CharColumn=0,u8RightSide=0;       ....}

First of all the function GLCD_Printf() was working perfectly on 8051 and works until the second character is displayed with HCS08AW.
 
*au8Text is the pointer to an array with undefined size, pushed in the stack at adress 0x084A. It contains the adress of the array 0x0838. In this location I can find the data 0x04 0x05 0x05 which is normal.
 
Once jumping into LcdPutChar, then the first line is u8CharColomn=0 and this variable is located in 0x083A which overlaps the au8Text....
Again, this issue come after the second displayed character
 
And there I don't find any workaround...
 
Any suggestion highly appreciated. Automotive customers are waiting their prototypes....
Best regards
Stephane Rey
 
 
Labels (1)
Tags (1)
0 Kudos
14 Replies

1,773 Views
CompilerGuru
NXP Employee
NXP Employee
You are not eventually using the address of a local array while the function containing the array did already return? That does not work in C.
I'm just wondering that both the pointer and the array are on the stack, but the pointer has a lower address.
If the pointer and the array are not both in the same function, then this wont work, and the overlapping is per language.

Daniel
0 Kudos

1,773 Views
stephane
Contributor I
I'm not sure to understand what you are saying Daniel...
 
When looking inside the stack, the pointer is at the adress 0x084A and the array is at 0x0838.
Both are in the stack. The pointer value is correct.
 
The array is defined in one function as a local array and the pointer of this array is given as a parameter when calling an other function
This second function starts by defining some local variables (so in stack) which have no relation with the array but on the same location than the array...
 
Is it a C language bad usage ?
 
Stephane
 
 
0 Kudos

1,773 Views
CompilerGuru
NXP Employee
NXP Employee
Your description sounds as if it would be ok, but in the end there is something wrong.
Can you show the code of the function actually defining the array?
That might clear it up.

What I meant was to actually return the address of an local array, I saw such code in the past.
E.g.
Code:
void fun(char** ptr){  char buf="Hello";  *ptr= buf; // illegal! buf is gone when fun returns.}

But it is ok to use the buf buffer inside of fun to call other functions with it.

Also check that the nothing writes behind the end of the array.

In the initial mail you also wrote of a "pointer to an array with undefined size", I wonder if this just states that the pointer does not know the size of the array it points to (in C pointers never know), or if this is really a pointer to an array, however I dont think that there are pointers to arrays with no size specified in C.

Anyway, all locals have to be above the SP (SP grows downwards), how does the SP look like before/during the function call?
For me the description sounds like the bug (regardless what it is) happens at the calling site not in the functions shown in the initial post.

Daniel

PS: just to double check, you are using the small memory model? In the tiny memory model, the stack could not be in around 0x800.


0 Kudos

1,773 Views
CompilerGuru
NXP Employee
NXP Employee
Ups, a typo. buf was supposed to be an array like this;
char buf[]="Hello";

Daniel

0 Kudos

1,773 Views
stephane
Contributor I
Hi Daniel and Bicmac,
 
I could make the code working by changing first the prototype of the UTIL_LongToAscii function as you said AND by defining the size of the array in the calling function DisplayValue.... Without specifying the size it doesn't work...
 
 
This way is still nice as I have not to define the array as a global array
I'm still surprise that what I've wrote is working in one compiler but not an other one.
 
Stephane


Message Edited by stephane on 2007-08-23 08:35 AM
0 Kudos

1,773 Views
CompilerGuru
NXP Employee
NXP Employee
>I'm still surprise that what I've wrote is working in one compiler but not an other one.

pure coincidence.
Looks like the other compiler did generate code which did by chance not overwrite the stack locations used for the array. However memory below the SP can be polluted at any time by an interrupt handler for example,
so such cases can cause bugs very difficult to find. Even with the other compiler, maybe at certain times the code did not work and you just did not notice at the times you looked there.

Daniel


0 Kudos

1,773 Views
stephane
Contributor I
you're right but that's not a great new as there are some machines in the field with this code !
 
In in cases, now it just works fine.
 
Thank you so much for your support. I do appreciate.
 
Best.
Stephane
0 Kudos

1,773 Views
bigmac
Specialist III
Hello Stephane,
 
Another alternative to that proposed by Daniel might be to simply define a global array of a suitable size to hold the ASCII digits, and write to this buffer within the UTIL_LongToAscii() function.  It is possible that this is what the original code may have intended.
 
Regards,
Mac
 
0 Kudos

1,773 Views
stephane
Contributor I
Hi Daniel,
 
Thanks for your support. I'm not an english mother tongue speaker, so I may not be so accurate when describing my issue. I do apologize for that.
 
The project has been created in small model.
The stack starts in 0x86F down to 0x76F (256 bytes) and is far from overflow.
 
Here is the full code.
 
GLCD_DisplayValue, makes conversion from a decimal value into ASCII in order to display on a graphic LCD.
 
Code:
/*-------------------------------------------------------------------------------Convert a digital value into an ASCII string GLCD_DisplayValue (U32 u32Value, U8 u8NumberOfIntegerDigits, U8 u8NumberOfDecimalDigits)  u32Value                = 32 bits Value to display  u8NumberOfIntegerDigits = Number of interger digits.       If this number is higher than the number of integer       digits, it will display the non significant '0'  u8NumberOfDecimalDigits = Number of decimal digits  *stFont                 = font to use     -------------------------------------------------------------------------------*/void GLCD_DisplayValue (U32 u32Value, U8 u8NumberOfIntegerDigits, U8 u8NumberOfDecimalDigits, FONT_DEF *stFont, U8 u8Type) { U8 *au8ValueToDisplay; au8ValueToDisplay = UTIL_LongToAscii(u32Value, u8NumberOfIntegerDigits, u8NumberOfDecimalDigits);  /* Display the string */ GLCD_Printf(au8ValueToDisplay, stFont, u8Type);}

The array au8ValueToDisplay contains the ASCII chars to display. The function call the GLCD_Printf function with the pointer to the array as one of the parameters.
 
When arriving in GLCD_Printf, everything works well.
 
Code:
/*-------------------------------------------------------------------------------Print a string on the LCD GLCD_Printf (U8 *au8Text)   *au8Text = string to display  *stFont  = font to use-------------------------------------------------------------------------------*/void GLCD_Printf (U8 *au8Text, FONT_DEF *stFont, U8 u8Type) { while(*au8Text != 0) {  LcdPutchar (*au8Text, stFont, u8Type);  au8Text++; }}

au8Text pointer is located in 0x84A and contains the value 0x838. The array (located in 0x838) contains the 3 ASCII bytes and everything is still correct there.
The function call LcdPutchar in a loop to display char after char as long as the NULL char has been detected. char is given as a parameter of LcdPutchar.
 
Code:
/*-------------------------------------------------------------------------------Print a char on the LCD GLCD_Putchar (U8 u8Char)  u8Char = char to display-------------------------------------------------------------------------------*/void LcdPutchar (U8 u8Char, FONT_DEF *stFont, U8 u8Type){ U8 u8CharColumn=0,u8RightSide=0;

 
When reaching the function, the pointer in 0x84A and the array in 0x838...0x83A are still correct.
But when running the U8 u8CharColumn=0, this variable located in 0x83A overwrites the last char of my array .... When coming back for the second time in the function, the char in 0x839 is then overwritten, and so on....
 
This code has been compiled with Keil C compiler for 8051 and was working well. This is why I was assuming the code correct and a bug in the compiler HC08... But I may have badly used the C language.
 
Do you see in my method something wrong ?
 
Best
Stephane

0 Kudos

1,773 Views
CompilerGuru
NXP Employee
NXP Employee
>
>Can you show the code of the function actually defining the array?
>
The code you showed does not define the array.
given that code I would wonder how this
UTIL_LongToAscii function is working, I could imagine that this function is the returning a pointer to a local array,
and if so thats not reliably working in C.

My guess is that UTIL_LongToAscii has a prototype like
char* UTIL_LongToAscii(U32 u32Value,U8 u8NumberOfIntegerDigits, U8 u8NumberOfDecimalDigits);
and that does only work if UTIL_LongToAscii would allocate the buffer on the heap (with malloc), but that's not what I would do for a
HC12. Definitely not.

So instead it should have a prototype like:

void UTIL_LongToAsciiIntoBuffer(U32 u32Value, char* buffer, unsigned int bufferSize, U8 u8NumberOfIntegerDigits, U8 u8NumberOfDecimalDigits);


And then be called with a reasonably sized buffer.

Daniel
0 Kudos

1,773 Views
CrasyCat
Specialist III
Hello
 
For point 1:
-------------
 
In default configuration, the linker does not report overlap between object defined at an absolute address using the @modifier and object allocated by the linker.
I would recommend to change the application .prm file to remove memory area used to allocate u8CopyRamToFlash from any area defined in the MEMORY block.
 
Alternatively you can ask the linker to generate a warning (or error) message when there is an overlap between variable defined with an absolute address and variable allocated by the linker.
In order to achieve that:
  - Start the IDE
  - Open your project 
  - Open the target settings dialog (press ALT+F7)
  - Switch to the "Linker for HC12" Panel
  - Press the "Message" button
  - In the "Disabled" Tab select line"L1912: Object <obj> overlaps with another (last addr: <addr>, object address: <objadr>"
   - If you want the Linker to generate a Warning when an overlap is detected, Click on "Warning". If you want the linker to generate an error message click on "Error"
  - Click on "OK" to close the "SmartLinker Message Settings" dialog.
  - Click OK to close the Target settings dialog.
 
Linker should generate a message now in case of overlap.
 
For Point 2:
------------------
 
Can you please check if you do not have a stack overflow here?
Just check the value of SP when you are in LcdPutchar.
Are you inside of memory area, where the linker has allocated data?
If this is the case, increase the stack size (In the .prm file increase the size specified in the STACKSIZE command).
 
If this does not help, I would recommend you to submit a service request for that.

Click here to submit a service request.

Make sure to attach a reproducible project and installed product information to the service request.
To generate the required information:
- Start CodeWarrior
- Open the project
- Select "Help" -> "Pack and Go" and follow instructions on the screen.

Attach the generated .zip file to the SR.
 
CrasyCat
0 Kudos

1,773 Views
stephane
Contributor I
Thanks for this answer CrasyCat...
 
Point1 is solved by changing the prm... Good point. I've also changed the overlap message category.
 
 
For Point 2, the stack size is largely good . The stack is set like that :
    MSTACK                   =  READ_WRITE   0x076F TO 0x086F;
and STACKSIZE = 100
 
Moreover as I'm usually doing, I've set a byte to value 0x55 in the bottom stack to check stack overflows... If the value changes then overflow has occured... In in my issue this is not the case.
In my project, the overlapped value is at adress 0x0838, far from the bottom stack.
 
I've copied the first message to freescale support without joining the project. I'm trying right now to reproduce the issue in a blank project in order to let freescale investigate further...
 
Stephane
 

 
0 Kudos

1,773 Views
bigmac
Specialist III
Hello Stephane,
 
A minor point - with your dedicated segment for the stack, I suspect you might have intended a stack size of 0x100, rather than 100.
 
Regards,
Mac
 
0 Kudos

1,773 Views
stephane
Contributor I
You have eagle eye Mac,
Thanks for your feedback. I've made the mistake when copying the code there, the exact code in the PRM is :
Code:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */    Z_RAM                    =  READ_WRITE   0x0070 TO 0x00FF;    RAM                      =  READ_WRITE   0x0100 TO 0x086F;    MSTACK                   =  READ_WRITE   0x076F TO 0x086F;    ROM                      =  READ_ONLY    0x1860 TO 0xFFAF;    ROM1                     =  READ_ONLY    0x0870 TO 0x17FF;    ROM2                     =  READ_ONLY    0xFFC0 TO 0xFFCB;END   PLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */    DEFAULT_RAM                         /* non-zero page variables */                                        INTO  RAM;    _PRESTART,                          /* startup code */    STARTUP,                            /* startup data structures */    ROM_VAR,                            /* constant variables */    STRINGS,                            /* string literals */    VIRTUAL_TABLE_SEGMENT,              /* C++ virtual table segment */    DEFAULT_ROM,    COPY                                /* copy down information: how to initialize variables */                                        INTO  ROM; /* ,ROM1,ROM2: To use "ROM1,ROM2" as well, pass the option -OnB=b to the compiler */    .stack     INTO  MSTACK ;    _DATA_ZEROPAGE,                     /* zero page variables */    MY_ZEROPAGE                         INTO  Z_RAM;ENDSTACKSIZE 0x100VECTOR 0 _Startup

 
so the stacksize is 256 bytes (0x100)
 
Since my last post I tried many things and nothing more.... defining the array size doesn't solve the issue... I don't know how to do a workaround there... And even if I find something, I need to understand why in order to prevent other parts of the code to crash...
 
Stephane
0 Kudos