【问题标题】:GCC Optimizes away an if clause which can't be optimizedGCC 优化掉无法优化的 if 子句
【发布时间】:2017-02-21 13:23:58
【问题描述】:

我创建了一个小代码来显示我遇到的错误

#include<stdlib.h>
#include<stdio.h>
int test(char * flag)
{
    char flagger = *flag;
    printf("test value %d", (int) flagger);
    if (flagger != 0x82)
    {
        exit(3);
    }
    else 
    {
        return 0;
    }
}


int main(void)
{
    char flag = 0x82, flag1 = 0x12, flag2 = 0x45;
    //char buf[256];
    test(&flag);
    test(&flag1);
    test(&flag2);
}

编译代码时: gcc -o tester test.c 或者 gcc -o tester test.c -O0

The resulting disassembly code for the function test in gdb is:  
Dump of assembler code for function test:
0x0804849b <+0>:    push   ebp
0x0804849c <+1>:    mov    ebp,esp
0x0804849e <+3>:    sub    esp,0x18
0x080484a1 <+6>:    mov    eax,DWORD PTR [ebp+0x8]
0x080484a4 <+9>:    movzx  eax,BYTE PTR [eax]
0x080484a7 <+12>:   mov    BYTE PTR [ebp-0x9],al
0x080484aa <+15>:   movsx  eax,BYTE PTR [ebp-0x9]
0x080484ae <+19>:   sub    esp,0x8
0x080484b1 <+22>:   push   eax
0x080484b2 <+23>:   push   0x80485c0
0x080484b7 <+28>:   call   0x8048350 <printf@plt>
0x080484bc <+33>:   add    esp,0x10
0x080484bf <+36>:   sub    esp,0xc
0x080484c2 <+39>:   push   0x3
0x080484c4 <+41>:   call   0x8048370 <exit@plt>
End of assembler dump.

如您所见,if 被优化为总是调用 exit 的版本。

我尝试了很多方法(恢复条件、使用 volatile 等),但我对为什么会发生这种情况一无所知。 请帮忙?

【问题讨论】:

  • 这就是您应该启用警告的原因。我在你的代码上得到了warning: comparison is always true due to limited range of data type [-Wtype-limits]
  • 在项目而不是这个小 poc 上,我使用了 -Wall,似乎我必须使用 -Wextra 才能显示。
  • 这也是为什么你不应该使用char 类型来存储字符以外的任何内容。如果需要存储值,请使用 uint8_t
  • @EfraimWeiss 如果您使用-pedantic-Wextra,似乎会添加此警告。始终将您的代码编译为gcc -std=c11 -pedantic-errors -Wall -Wextra,这样您就可以避免许多错误。

标签: c gcc compiler-optimization


【解决方案1】:

在您的系统上,char 的范围是 -128+127。但是0x82 是十进制的130。从130 &gt; 127开始,这个测试永远不会成功。

要修复您可以使用的代码:

if ( flagger != '\x82' )

if ( (unsigned char)flagger != 0x82 )

请注意,早期代码 char flag = 0x82 是一个超出范围的赋值,这是实现定义的行为。您可以考虑对所有这些变量使用unsigned charuint8_t

【讨论】:

    猜你喜欢
    • 2017-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2011-05-18
    • 2010-09-07
    相关资源
    最近更新 更多