为什么优化无缘无故更改我的指针地址?

时间:2019-01-30 23:21:31

标签: c optimization

我在嵌入式C应用程序中的优化遇到问题。指针的地址意外更改为0x0并破坏了我的代码。

我正在使用GNU MCU Eclipse ARM嵌入式GCC工具链。我正在使用通过SPI与之通信的传感器。该传感器具有8个配置寄存器,每个16位。 我将配置的本地副本保存在名为“ hallsensor_zTleConfig”的结构中 我会定期读取传感器的存储配置(“ zTleSensorConfig”),并将其与本地副本进行比较,以查看是否发生了内存损坏。

在没有优化的情况下,此过程仍然有效。

通过优化,在下面的代码中,没有明显原因,指向主/本地副本的指针突然变为0x0。

// Master copy of configuration of the TLE chips
static TLE5012B_zCONFIG hallsensor_zTleConfig[ HALLSENSOR_COUNT ];

static void Hallsensor_VerifyConfig( HALLSENSOR_eUNIT eUnit )
{
    TLE5012B_zCONFIG zTleSensorConfig;
    uint16* pu16MasterConfigPointer = &hallsensor_zTleConfig[ eUnit ];
    uint16* pu16SensorConfigPointer = &zTleSensorConfig;
    uint8 u8Index;

    // Read all configuration parameters
    (void)Hallsensor_ReadRegister( TLE5012B_MOD_2, &zTleSensorConfig, sizeof( TLE5012B_zCONFIG ) );

    // Copy over configurations modified by Auto-calibration and reserved bits
    hallsensor_zTleConfig[ eUnit ].zMod3.u12ANG_BASE     =     zTleSensorConfig.zMod3.u12ANG_BASE;
    hallsensor_zTleConfig[ eUnit ].zSynch.i12AmpSynch    =     zTleSensorConfig.zSynch.i12AmpSynch;
    hallsensor_zTleConfig[ eUnit ].zOffsetX.i12XOffset   = zTleSensorConfig.zOffsetX.i12XOffset;
    hallsensor_zTleConfig[ eUnit ].zOffsetY.i12YOffset   = zTleSensorConfig.zOffsetY.i12YOffset;
    hallsensor_zTleConfig[ eUnit ].zMod4.u7TCO_X_T       = zTleSensorConfig.zMod4.u7TCO_X_T;
    hallsensor_zTleConfig[ eUnit ].zTcoY.u7TCO_Y_T       = zTleSensorConfig.zTcoY.u7TCO_Y_T;
    hallsensor_zTleConfig[ eUnit ].zMod2.u1Reserved      = zTleSensorConfig.zMod2.u1Reserved;
    hallsensor_zTleConfig[ eUnit ].zMod4.u1Reserved      = zTleSensorConfig.zMod4.u1Reserved;
    hallsensor_zTleConfig[ eUnit ].zOffsetX.u4Reserved   = zTleSensorConfig.zOffsetX.u4Reserved;
    hallsensor_zTleConfig[ eUnit ].zOffsetY.u4Reserved   = zTleSensorConfig.zOffsetY.u4Reserved;
    hallsensor_zTleConfig[ eUnit ].zSynch.u4Reserved     = zTleSensorConfig.zSynch.u4Reserved;

    // Compare local Master config setting to sensor settings and look for corrupted data
    for ( u8Index = 0; u8Index < TLE5012B_CONFIG_REG_COUNT; u8Index++ )
    {
        // Configuration invalid?
        if ( pu16MasterConfigPointer[u8Index] != pu16SensorConfigPointer[u8Index] )
        {
            hallsensor_bConfigOk[ eUnit ] = FALSE;
        }
    }

    // Data corrupted?
    if ( !hallsensor_bConfigOk[ eUnit ] )
    {
        // Do stuff
    }
}

在函数开始时,pu16MasterConfigPointer和pu16SensorConfigPointer正确保存其相应结构的地址。但是,就在第一个for循环之前,pu16MasterConfigPointer更改为0x0,并且所有for循环条件的结果均为TRUE。

我尝试了volatile的多种组合,以用于不同的变量和指针,结果仍然以其他各种方式破坏代码(例如,for循环不会分支出if语句查看asm代码,导致语句始终转到“ hallsensor_bConfigOk [eUnit] = FALSE;“)

PS:非常欢迎您学习如何保护代码免受优化问题的帮助。

调试器的屏幕快照,其中显示了指针= 0x0(带有asm代码)

enter image description here

1 个答案:

答案 0 :(得分:0)

@John Bollinger说得对,指针违反了我不知道的严格的别名规则。 post中对此规则有很好的解释。

用memcmp代替for循环就可以了。