gcc-O2创建了一个无休止的循环,可能是因为未定义的行为

gcc-O2创建了一个无休止的循环,可能是因为未定义的行为,c,gcc,C,Gcc,我写这个C代码是为了解决代码13 2020的出现。我知道,用蛮力来解决这个问题可能是不可行的,但是程序给出了示例输入的正确答案 如果我尝试让gcc优化代码,它会使用-O1给出正确的结果,但会使用-O2创建一个无休止的循环。经过所有的研究,我的结论是我的代码中存在未定义的行为,我想这与“发现”的概率永远不会高于0有关,因此“时间”将溢出 问题是:有人知道如何修补未定义的行为吗? “-Wall-Wextra-pedantic”甚至不要发出警告或其他什么 我就是找不到解决办法。例如,如果我将while

我写这个C代码是为了解决代码13 2020的出现。我知道,用蛮力来解决这个问题可能是不可行的,但是程序给出了示例输入的正确答案

如果我尝试让gcc优化代码,它会使用-O1给出正确的结果,但会使用-O2创建一个无休止的循环。经过所有的研究,我的结论是我的代码中存在未定义的行为,我想这与“发现”的概率永远不会高于0有关,因此“时间”将溢出

问题是:有人知道如何修补未定义的行为吗?

“-Wall-Wextra-pedantic”甚至不要发出警告或其他什么

我就是找不到解决办法。例如,如果我将while循环的头更改为(!found&&time<1000000000),这样就不会发生溢出,当使用-O2编译时,它会立即以10000000003的时间值中断循环,但仍然使用-O1给出正确的结果

这是代码,正确的结果是“1068781”:

#包括
int main()
{
无符号整数总线[]={7,0,13,2,59,1,31,0,19};
使用的无符号整数总线=9;
无符号整数i=0;
找到的无符号整数=0;
无符号长时间=0;
无符号整数偏移量=0;
无符号整数增量=7;
而(!found){
时间+=增量;
偏移量=0;
对于(i=0;i

编辑:感谢KamilCuk指出,代码正在访问数组,并教授如何发现它正在访问。通过在“busses”数组末尾添加另一个0来解决问题,因此也将“busses_used”设置为10而不是9。

我不理解代码,也不缩进到,但循环很奇怪。无论如何:

“-Wall-Wextra-pedantic”甚至不要发出警告或其他什么

还有其他检测UB的方法!使用更多的
-fsanize=*
选项编译代码,结果如下:

+ gcc -Wall -Wextra -ggdb3 -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize-address-use-after-scope /tmp/1.c
/tmp/1.c:22:29: runtime error: index 9 out of bounds for type 'unsigned int [9]'
/tmp/1.c:22:29: runtime error: load of address 0x7ffc48c7a894 with insufficient space for an object of type 'unsigned int'
0x7ffc48c7a894: note: pointer points here
  13 00 00 00 60 60 00 00  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  08 aa c7 48 fc 7f 00 00
              ^ 
=================================================================
==73835==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc48c7a894 at pc 0x55c28a5bf773 bp 0x7ffc48c7a800 sp 0x7ffc48c7a7f0
READ of size 4 at 0x7ffc48c7a894 thread T0
    #0 0x55c28a5bf772 in main /tmp/1.c:22
    #1 0x7f0060bd1151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
    #2 0x55c28a5bf12d in _start (/tmp/tmp.qv8ZsZofOJ.out+0x112d)

Address 0x7ffc48c7a894 is located in stack of thread T0 at offset 84 in frame
    #0 0x55c28a5bf208 in main /tmp/1.c:3

  This frame has 1 object(s):
    [48, 84) 'busses' (line 4) <== Memory access at offset 84 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/1.c:22 in main
Shadow bytes around the buggy address:
  0x1000091874c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000091874d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000091874e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000091874f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100009187500: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 f1 f1 00 00
=>0x100009187510: 00 00[04]f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
  0x100009187520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100009187530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100009187540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100009187550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100009187560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==73835==ABORTING
有人知道如何修补未定义的行为吗


不知道,但是写一个算法,它不会访问超出范围的数组。

(时间+偏移量)%busses[i]
创建一个未定义的行为,因为
总线包含零,除法/从除法中得到提示是一个错误。有趣的是,
%busses[i]
从不为零,因为
offset+=busses[++i]
-
i
每个循环递增两次。即使修复UB,因为循环行为不依赖于任何输入,也不输出任何内容,优化器只需准确地确定
printf
之前的所有代码将提前执行什么操作,基本上只需将其替换为
unsigned long long time=the_答案语句。-或者,如果t可以证明循环永不结束,那么a
表示(;;)等效。
offset += busses[++i];