Format String Crash
Answer
8/8/17 2:45 PM

Hello,

my code is based on the Data-Logger-Demo and uses sprintf to fill a buffer with formated strings. Most of the values used to fill them are integers, but some are float-values. When I use the %d-specifier for these they're of course displayed wrong, but everythings running fine.

The moment I change them to %f i get a heap and stack collision. This happens even when i use a constant float value.

Im not very familiar with the magic behind the format functions. Do they acquire more space in memory when displaying float values ?

Any suggestions to get this running ?

kind regards

Jan H.

+1 (1 Vote)
RE: Format String Crash
Answer
8/9/17 12:36 PM as a reply to Jan Hinrichsen.

Hello Jan,

generally, sprintf() is an unsafe function, because it can write on unallocated memory or (unintentionally) overwrite other variables, if they are located next to each other in the memory. This is called a buffer overflow. Additionally, float values are promoted to double in sprintf(). That means, every "%f" identifier occupies 8 Byte of memory, instead of the 4 Byte used for integers or floats.

Perhaps the buffer is too small and/or in an unsafe region, and therefore unable to accommodate the 4 extra bytes per value?

If not, could you elaborate on what you mean by "get a heap and stack collision"? Is this an error logged in the console on runtime? Can you provide me with a code example or instructions on what to change in the Data Logger demo, to reproduce this exact behaviour?

Kind regards,
Franjo

+2 (2 Votes)
RE: Format String Crash
Answer
8/10/17 11:57 AM as a reply to Franjo Stjepandic.
Hello guys!

As Franjo already told, the libc formatting functions are quite unsafe in some conditions, but there are other issues that can cause a crash.

The firmware of Bosch XDK, when it starts to run, is already running on the FreeRTOS, so the memory used by the libc functions resides on the stack of the currrent thread, and not the reserved stack space made in linker script file.

So, as a first test, my suggesttion is: try to increase the stack size of all threads that use libc stdlib/stdio functions, I think 256 words is sufficient (1kbyte), but you can also increase to even more high value to validate if the crash is by stack overflow or not.

Yes the FreeRTOS has the stack tracing feature, but it only runs in specific moments of kernel execution, in general form is only during a context swittch, since the libc functions executes in same thread that have been called, the stack trace will not be triggered until a context switch occurs, and if crashing is occuring before this event the stack trace will no able to track it as well.

Additionally you can use some more simple formats instead of float, try to convert your variable to a fixed point Q-fractional value then format is as a integer fashion.

Please feel free to ask more questions.

Best

Felipe
+1 (1 Vote)
RE: Format String Crash
Answer
8/11/17 10:10 AM as a reply to Felipe Neves.

Hi,

thank you for the fast response. I made quite a few changes to the original code, so it propably wont be that easy to reproduce. The problem happens in a thread that recieves data from a queue and fills a buffer with it, which is then periodically written by another thread.

The "heap and stack collision" is indeed the error message recieved via the console. Even after increasing the stack size of the thread to 1500 words i keep getting the same problem. 

I have found a work around by using a little ftoa function, but it would be interesting to know why this happens. So you would suggest to increase the size of all threads ? Do you know if the stdlib function is running in the stack of the executing thread or somewhere else ?

kind regards

Jan

PS: here a little code snippet, but I don't think this shows the real problem.

//New Version:
eventBuffer.length += sprintf(
						eventBuffer.data + eventBuffer.length, "%s;%s;%s;",
						ftoa(CONTAINER(sensorData).unit_data.calibratedAccelData.xAxisData,4,buff[0]),
						ftoa(CONTAINER(sensorData).unit_data.calibratedAccelData.yAxisData,4,buff[1]),
						ftoa(CONTAINER(sensorData).unit_data.calibratedAccelData.zAxisData,4,buff[2]));
//Old one
eventBuffer.length += sprintf(
						eventBuffer.data + eventBuffer.length, "%3.2f;%3.2f;%3.2f;",
						CONTAINER(sensorData).unit_data.calibratedAccelData.xAxisData,
						CONTAINER(sensorData).unit_data.calibratedAccelData.yAxisData,
						CONTAINER(sensorData).unit_data.calibratedAccelData.zAxisData);

 

0 (0 Votes)
RE: Format String Crash
Answer
8/11/17 5:00 PM as a reply to Jan Hinrichsen.

Hello Jan,

a stack and heap collision indicates that there is an issue with your memory management because the size of used variables is growing too large.
In many cases this is caused by recursive memory allocating.

An disproportionate increase of the stack size, as Felipe suggested, may temporarily fix the issue, but is no absolute solution.

Your workaround with the ftoa function confirms my assumption, that it converts the larger float values into smaller character values. This causes that the used array does not grow too large.  

Therefore I do not recommend to increase the stack depth of all threads. To solve this, I recommend calculating or analyse how much your arrays are growing during the application runtime and then take action and reduce the size of them as far as possible.

Only if no further reduction is possible, increase the stack size.

Please let me know if this is helpful and do not hesitate to ask if you have further questions.

Kind regards,
Franjo

0 (0 Votes)