1

次のコードを検討してください。

#define TRANSLATOR_requestElectricityMeterWrite()  do{addr = word_getAddress(); value = word_getValue(); }while(0)

uint16_t value;
uint8_t addr;

bool dispatcher(void)
{
    TRANSLATOR_requestElectricityMeterWrite(); 
    return true;
} // AFTER this point (during debug) program goes to default handler

int main(void)
{
   if(dispatcher())
      continue;
      . . . .
      . . . . 
}

uint16_t word_getValue(void)
{
    uint16_t value;
    sscanf("ABCD", "%4x", (unsigned int *)&value);
    return value;
}

uint8_t word_getAddress(void)
{
    uint8_t address;
    sscanf("00", "%2x", (unsigned int *)&address);
        ;
    return address;
}

上記のコードを実行すると、内部のステートメントifによってプログラムがクラッシュします (既定のハンドラーに移動します)。

しかし、2 つの (word_getValueおよび word_ getAddres) 関数を次のように変更すると、次のようになります。

uint16_t word_getValue(void)
{
    uint16_t value;
    int i = 0;i++;
    i = sscanf(WORD_getValueString(), "%4x", (unsigned int *)(&value));
    return value;
}

uint8_t word_getAddress(void)
{
    uint8_t address;
    int i = 0;i++;
    i = sscanf(WORD_getNameString(), "%2x", (unsigned int *)(&address));
    return address;
}

できます。ダミーiがその問題を解決すると思われる場合の追加。しかし、なぜそれが逆に機能しないのでしょうか?

GNU ARM v4.8.3 ツールチェーン

4

2 に答える 2

3

どちらの関数も未定義の動作を呼び出すため、何でも発生する可能性があります。追加のローカル変数を追加すると、宛先変数の場所が変更され、不適切なサイズの影響が隠されます。

sscanf("ABCD", "%4x", (unsigned int *)&value);

sscanfsizeof(unsigned int)バイト (おそらく 4) を variableに格納しますvalueが、これには 2 バイトしかありません。

sscanf(WORD_getNameString(), "%2x", (unsigned int *)(&address));

1 バイトしかないsizeof(unsigned int)variable にバイトを格納します。address

この問題を解決する最も簡単な方法は、 に解析して、unsigned int解析された値を宛先に個別に格納するか、単純に値を返すことです。

uint16_t word_getValue(void) {
    unsigned int value;
    if (sscanf(WORD_getValueString(), "%4x", &value) == 1)
        return value;
    // could not parse a value, return some default value or error code
    return 0;
}

uint8_t word_getAddress(void) {
    unsigned int address;
    if (sscanf(WORD_getNameString(), "%2x", &address) == 1)
        return address;
    // could not parse a value, return some default value or error code
    return 0;
}

解析された値が宛先タイプの範囲内にあるかどうかを確認することもできますが、解析をそれぞれ 4 桁と 2 桁の 16 進数に制限しているため、オーバーフローは発生しません。

于 2016-08-12T12:52:37.793 に答える