2011-12-09 112 views
1

我在使用gcc44和gdb调试在64位Linux CentOS 5.7上运行的ANSI C程序。我在程序中有以下循环:为什么从我的c程序打印的变量的值与gdb打印的值不同?

for (ii = 1; ii < 10001; ii++) { 
    time_sec[ii] = (10326) * dt - UI0_offset; /* in seconds */ 
    printf("\ntime_sec[%d] = %16.15e, dt = %16.15e, UI0_offset = %26.25e\n", 
      ii, time_sec[ii], dt, UI0_offset); 
} 

其中time_sec,dt和UI0_offset是双打。相关的GDB会议是:

(gdb) p time_sec[1] 
$2 = 2.9874137906250006e-15 
(gdb) p (10326) * dt - UI0_offset 
$3 = 2.9874137906120759e-15 

为什么2美元和3美元不同的数字? $ 2 = time_sec [1]由c程序计算,而$ 3是相同的等式,但在gdb中计算。

我将一个Matlab算法移植到C和Matlab(在不同的机器上运行)完全匹配gdb编号$ 3,我需要这个精度。任何人都知道这里会发生什么,以及如何解决?

更新:经过一些调试后,似乎区别在于UI0_offset的值。我探讨GDB透露此变量的一些额外的数字(注:任何人都知道一个更好的方式来看看在gdb更多的数字我尝试过的sprintf的语句,但无法得到它的工作?):

(gdb) p UI0_offset -1e-10 
$5 = 3.2570125862093849e-12 

我然后插在上面的原始张贴所示的循环中的printf()的代码,而当它在gdb运行它示出了:

time_sec[1] = 2.987413790625001e-15, dt = 1.000000000000000e-14, 
UI0_offset = 1.0325701258620937565691357e-10 

因此,概括地说:

1.032570125862093849e-10 (from gdb command line, the correct value) 
1.0325701258620937565691357e-10 (from program's printf statement, NOT correct value) 

任何理论原因的值为UI0_offset i在gdb命令行和运行在gdb中的程序之间有什么不同(以及如何使程序与gdb命令行一致)?

+0

当您使用gcc编译应用程序时,您正在使用哪种优化级别? – Steve

+0

我不打电话给任何人,所以无论是默认的。编译时间对我来说不是问题。我应该使用-O2吗? – ggkmath

+0

您能向我们展示一个展示此问题的小型完整程序吗?例如,您向我们展示的结果仅指'time_sec [1]';您不需要计算其他10000个值来证明问题。尝试将代码缩小到声明和初始化相关变量的东西,并告诉我们一些我们可以尝试的东西。 (事实上​​,我不知道'time_sec','dt'和'UI0_offset'的值是什么。) –

回答

4

我不确定x64体系结构是否包含与x86一样的80位(long double)FP寄存器,但当x86结构中存在中间结果(即第一个乘法)时,通常会产生像x86这样的结果在80位寄存器中,而不是刷新回缓存/ RAM。有效地进行部分计算是以更高的精度完成的,因此会产生不同的结果。

GCC有一个选项(-ffloat-store,如果我的内存服务的话)会导致中间结果被刷新回64位精度。试着启用它,看看你是否符合GDB/Matlab结果。

+0

嗯,我得到编译错误:gcc44:无法识别的选项'-store',和其中四个:cc1:错误:无法识别的命令行选项“-ffloat”。安置顺序是否重要?我正在使用#gcc44 -g -ansi -ffloat -store infile.c -o out -lm – ggkmath

+0

@ggkmath:这是一个选项,-ffloat-store('t'和' - '之间没有空格)。 –

+0

哦,我的错。好吧,它现在编译,但我看到完全相同的结果(没有改变)。 – ggkmath

相关问题