Home > Enterprise >  GCC optimization of (char) pointers makes no sense
GCC optimization of (char) pointers makes no sense

Time:02-25

I am using STM32 Cube IDE version 1.8.0 for a STM32 MCU project. Builder settings are default. It is set to "External builder".

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for STM32 9-2020-q2-update.20201001-1621) 9.3.1 20200408 (release) Copyright (C) 2019 Free Software Foundation, Inc.

In Properties->C/C Build->Settings->Tool Settings the MCU GCC compiler command is gcc -c and the content of "All options" is

-mcpu=cortex-m4 -std=gnu11 '-D__weak=__attribute__((weak))' '-D__packed=__attribute__((__packed__))' -DUSE_HAL_DRIVER -DSTM32F412Rx -c -I../Drivers/STM32F4xx_HAL_Driver/Inc -I../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy -I../Middlewares/Third_Party/FreeRTOS/Source/include -I../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 -I../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F -I../Middlewares/ST/STM32_USB_Device_Library/Core/Inc -I../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -I../Drivers/CMSIS/Device/ST/STM32F4xx/Include -I../Drivers/CMSIS/Include -Os -ffunction-sections -fdata-sections -Wall -fstack-usage --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb

Pay attention to -Os!

Now, if I use the following code (snippet)

bool ESP32_WifiCommCmds_ConnectToAP ( char* ssid, char* password, char* mac )
{
    char cmd [ 96 ] = { 0 };
    char *ssidEscaped, *passwordEscaped;
    ESP32_ModuleCommCmds_EscapeSpecialCharacters ( ssid, &ssidEscaped );
    if ( ssidEscaped == NULL )
    {
        return false;
    }
    ESP32_ModuleCommCmds_EscapeSpecialCharacters ( password, &passwordEscaped );
    if ( passwordEscaped == NULL )
    {
        free ( ssidEscaped );
        return false;
    }
    if ( strlen(ssidEscaped)   strlen(passwordEscaped)   strlen(mac)   17 > sizeof(cmd) )
    {
        free ( ssidEscaped );
        free ( passwordEscaped );
        return false;
    }
    // THE FOLLOWING IF ELSE WILL GET OPTIMIZED !!!!!!
    if ( mac == NULL )
    {
        // THIS WILL GET OPTIMIZED OUT
        sprintf ( cmd, "AT CWJAP=\"%s\",\"%s\",,,1", ssidEscaped, passwordEscaped );
    }
    else
    {
        // THIS WILL STAY
        sprintf ( cmd, "AT CWJAP=\"%s\",\"%s\",\"%s\",,1", ssidEscaped, passwordEscaped, mac );
    }
    free ( ssidEscaped );
    free ( passwordEscaped );
    char buffer [ 48 ] = { 0 };
    // Send cmd to ESP is left out here, for simplification
}

And in the business logic, call this function with only: success = ESP32_WifiCommCmds_ConnectToAP ( data->ssid, data->password, NULL );

One would suggest, that the optimized code will remove the if ( mac == NULL ) because it will always be true. But in fact the opposite is the case.

The issue lies in the line with strlen(mac) but I do not know why this is. I need explanaition because I am afraid whatever I do wrong here, will have not yet seen impact on the rest of my code.

PS: If you want to check for yourself, simply search the resulting binary to include the "AT CWJAP=..." strings. Only one of them is in there (except you switch off the optimisations).

CodePudding user response:

If you call strlen(mac) then the compiler is allowed to assume that mac is never null.

The reasoning is this:

A) if mac is not null, then it has assumed correctly and everything it does based on that assumption is correct.

B) if mac is null then you call strlen(NULL) which triggers undefined behaviour. Since undefined behaviour means it can do absolutely anything, then anything it does must be correct.

Therefore whatever the argument when you call this function, the implementation is correct to assume that mac is not null.

Note that this all happens when compiling the implementation of the function, it never gets as far as looking at what you do in the code that calls the function, as you had supposed.

  • Related