cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with optimization with Gcc on snprintf and FreeRTOS queue.c

JMART.22
Associate II

I have compilation warning only with -O2 optimization (no warning with -O0) and i don't understand why, the code seems to be correct.

My environnement: STM32F103VD + STM32CubeIDE V1.2.0 (Gcc 7.3.1)

The code is the following for the first warning:

#define REC_DATE_HOUR_LENGTH  (7u) 
 
static CHAR acRecordDate[REC_DATE_HOUR_LENGTH] = {0};
 
snprintf((char*)acRecordDate,REC_DATE_HOUR_LENGTH,"%.2d%.2d%.2d", sDateTime.u8Day, sDateTime.u8Month, (U8)sDateTime.u16Year);

This line of code introduces the following warning:

warning: '%.2d' directive output may be truncated writing between 2 and 3 bytes into a region of size between 1 and 3 [-Wformat-truncation=]

I think the warning is a false positive. The output directive %.2d limit to two bytes the writing in acRecordDate buffer. Therefore, the REC_DATE_HOUR_LENGTH = 7 is sufficient and no warning has to be raised.

Another warning is in FreeRTOS queue management. And i clearly don't understand why it's generated.

The warning is:

FreeRTOS/queue.c:2067:3: warning: argument 2 null where non-null expected [-Wnonnull]

The line of code:

( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */

This warning is generated by -finline-small-functions optimization option.

So if someone solve these problems, any help is really appreciated !

Best regards,

JLM.

4 REPLIES 4
TDK
Guru

> The output directive %.2d limit to two bytes the writing in acRecordDate buffer

"%.2d" does not limit the size to 2 characters. For example, 255 is still printed as 3 characters.

https://onlinegdb.com/SkdYmWE6L

For the second, how is pvItemToQueue defined?

If you feel a post has answered your question, please click "Accept as Solution".
JMART.22
Associate II

Hi TDK,

Thank you for your answer

You are clearly right for snprintf format specification. The number after a % doesn't truncate the resulting string. Therefore, the compiler is right. Only float values can be truncated by a format precision (i.e. %.2f with a value of 52.6325 will be printed as 52.63).

For the second problem it's a call to a FreeRTOS function that causes this warning.

It's quite tricky due to optimization and function inlining.

In gcc web site here:

https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options

The -Wnonnull compiler option is:

-Wnonnull
Warn about passing a null pointer for arguments marked as requiring a non-null value by the nonnull function attribute.
 
-Wnonnull is included in -Wall and -Wformat. It can be disabled with the -Wno-nonnull option.

There is no nonnull attribute in my code and in FreeRTOS source code.

Example of nonnull attribute for gcc compiler:

nonnull (arg-index, ...)
The nonnull attribute specifies that some function parameters should be non-null pointers. For instance, the declaration:
          extern void *
          my_memcpy (void *dest, const void *src, size_t len)
                  __attribute__((nonnull (1, 2)));
     
causes the compiler to check that, in calls to my_memcpy, arguments dest and src are non-null. If the compiler determines that a null pointer is passed in an argument slot marked as non-null, and the -Wnonnull option is enabled, a warning is issued. The compiler may also choose to make optimizations based on the knowledge that certain function arguments will not be null.
 
If no argument index list is given to the nonnull attribute, all pointer arguments are marked as non-null. To illustrate, the following declaration is equivalent to the previous example:
 
          extern void *
          my_memcpy (void *dest, const void *src, size_t len)
                  __attribute__((nonnull));

The call tree is the following in my case which generates the warning:

It begins with QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) function.

 xQueueCreateMutex( const uint8_t ucQueueType )
       => call prvInitialiseMutex with argument pxNewQueue != NULL
 
static void prvInitialiseMutex( Queue_t *pxNewQueue )
     => call ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
    with second argument NULL.
 
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )      
     (with pvItemToQueue = NULL) 
   => call prvCopyDataToQueue with pvItemToQueue = NULL
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
 
And finally 
static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
 
   => call ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */
		

So the compiler identify this calling tree and checks non null parameter despite any __attribute__(nonnull) setting.

This warning shouldn't be set by the compiler (in my mind).

TDK
Guru

So the compiler is correctly deducing that you are calling memcpy(..., NULL, ...)? Why would that warning be invalid? I'm not seeing your argument. memcpy needs non-null arguments for src and dest.

If you feel a post has answered your question, please click "Accept as Solution".
JMART.22
Associate II

Not exactly, there is another parameter which forbid to call memcpy with a NULL parameter before. Therefore the memcpy isn't called with a NULL parameter.

The compiler checks only the memcpy parameter and not the whole execution.

So the compiler identify a possible call to memcpy with a NULL parameter (in real execution, this is not the case). I think that warning should not be because there is no  __attribute__(nonnull) setting for memcpy (in the string.h file).