使用GCC(至少6.1.1,5.3.1,4.1.2)和优化-O3(以及-O2)时,以下程序未编译为正确的可执行文件。 GCC使用-O0(和-O1)生成正确的可执行文件。
输出应为(-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
代替(-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
有人知道原因吗?这是GCC的错误吗? 谢谢!
#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);
}
答案 0 :(得分:2)
(至少)有一个错误。
在merge
中你有:
double arr1[10],arr2[10];
工作数组需要大一个才能符合监视值(9999
),因此您需要:
double arr1[11],arr2[11];
答案 1 :(得分:1)
我在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
当然,算法看起来好像做了一些奇怪的事情,但至少编译器是一致的。
答案 2 :(得分:1)
在断言它是正确的之前检查你自己的代码并责备编译器。 (The first rule of programming: it's always your fault)
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'