[英]GCC -O3 6.1.1, 5.3.1, 4.1.2 fails to compile a correct executable (recursive merge sort in C)
The following program is not compiled into a correct executable when using GCC (at least 6.1.1, 5.3.1, 4.1.2) and with optimization -O3 (and also -O2). 使用GCC(至少6.1.1、5.3.1、4.1.2)和优化-O3(以及-O2)时,以下程序未编译为正确的可执行文件。 GCC generates a correct executable with -O0 (and -O1).
GCC使用-O0(和-O1)生成正确的可执行文件。
The output should be (-O0): 输出应为(-O0):
Sorted array: 1.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 9.00010.0009999.00012.00013.00014.00015.00016.00017.00018.0001 9.00020.000
instead of (-O3): 而不是(-O3):
Sorted array:11.00012.00013.00014.00015.00016.00017.00018.00019.00020.0009999.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 9.00010.000
Has anybody an idea of the reason? 有人知道原因吗? Is it a bug of GCC?
这是GCC的错误吗? Thanks!
谢谢!
#include <stdio.h>
#include <stdlib.h>
double arr[20] = {20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
int merge(double arr[],int l,int m,int h)
{
double arr1[10],arr2[10];
int n1,n2,i,j,k;
n1=m-l+1; n2=h-m;
for(i=0; i<n1; i++) arr1[i]=arr[l+i];
for(j=0; j<n2; j++) arr2[j]=arr[m+j+1];
arr1[i]=9999; arr2[j]=9999; i=0; j=0;
for(k=l; k<=h; k++) {
if(arr1[i]<=arr2[j])
arr[k]=arr1[i++];
else
arr[k]=arr2[j++];
}
return 0;
}
int merge_sort(double arr[],int low,int high)
{
int mid;
if(low<high) {
mid=(low+high)/2;
merge_sort(arr,low,mid);
merge_sort(arr,mid+1,high);
merge(arr,low,mid,high);
}
return 0;
}
int main()
{
int i,n=20;
merge_sort(arr,0,n-1);
printf("Sorted array:");
for(i=0; i<n; i++)
printf("%6.3f",arr[i]);
printf("\n");
exit(0);
}
There is (at least) one bug. (至少)有一个错误。
In merge
you have: 在
merge
您有:
double arr1[10],arr2[10];
The work arrays needs to be one larger to fit the watch value ( 9999
), so you need: 工作数组需要大一个以适合监视值(
9999
),因此您需要:
double arr1[11],arr2[11];
I see identical results between -O0 and -O3 on gcc 5.4.0: 我在gcc 5.4.0上看到-O0和-O3之间相同的结果:
evaitl@bb ~/se $ gcc -Wall -O0 -o foo foo.c
evaitl@bb ~/se $ ./foo
Sorted array:11.000 12.000 13.000 14.000 15.000 16.000 17.000 18.000 19.000 20.000 9999.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 9.000 10.000
evaitl@bb ~/se $ gcc -Wall -O3 -o foo foo.c
evaitl@bb ~/se $ ./foo
Sorted array:11.000 12.000 13.000 14.000 15.000 16.000 17.000 18.000 19.000 20.000 9999.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 9.000 10.000
Of course, the algorithm seems like it is doing strange things, but at least the compiler is consistent. 当然,该算法似乎在做奇怪的事情,但至少编译器是一致的。
Check your own code before you assert it is correct and blame the compiler. 在断言您的代码正确无误之前,请检查自己的代码并责怪编译器。 ( The first rule of programming: it's always your fault )
( 编程的第一条规则:总是你的错 )
AddressSanitizer shows the problem: AddressSanitizer显示了问题:
=================================================================
==13359==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff0e9e3f40 at pc 0x000000400c59 bp 0x7fff0e9e3e80 sp 0x7fff0e9e3e70
WRITE of size 8 at 0x7fff0e9e3f40 thread T0
#0 0x400c58 in merge /tmp/sort.c:15
#1 0x400f9f in merge_sort /tmp/sort.c:34
#2 0x400fcc in main /tmp/sort.c:43
#3 0x7f3d7416857f in __libc_start_main (/lib64/libc.so.6+0x2057f)
#4 0x400928 in _start (/tmp/a.out+0x400928)
Address 0x7fff0e9e3f40 is located in stack of thread T0 at offset 112 in frame
#0 0x400a05 in merge /tmp/sort.c:7
This frame has 2 object(s):
[32, 112) 'arr1' <== Memory access at offset 112 overflows this variable
[160, 240) 'arr2'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.