2013-03-08 34 views
-6

gnu编译器,从命令行运行,使用崇高的文本2没有mods。代码看似无关的变化给出了不同的结果

简单的程序显示一个递归函数的运行时间,该函数使用随机数在0和1之间的均匀分布的5000索引数组并添加它们(意味着您应该在2500的球场中获得某个值)。下面的代码一贯正常工作,并产生合理接近预期值的东西。然而,添加一个新的线/选项卡到其中一个cout中,并且所有的事情都会在一个手筐中进入地狱(见下文)。

#include <iostream> 
#include <stdlib.h> 
#include <time.h> 
using namespace std; 

double sumOfRandomNumbers(double arrayToFill[], int lengthOfArray){ 
    if(lengthOfArray == 0) return arrayToFill[lengthOfArray]; 
    return arrayToFill[lengthOfArray] + sumOfRandomNumbers(arrayToFill, lengthOfArray - 1); 
} 

double seconds(){return double(clock())/CLOCKS_PER_SEC;} 

int main(){ 

    int sizeOfArray = 5000; 
    double sum = 0.0, deltaT = 0.0, array[sizeOfArray]; 
    srand(time(NULL)); 

    for(int i = 0; i < sizeOfArray; i++) array[i] = double(rand())/double(RAND_MAX); 

    cout << "\nRecursive Method\n"; 
    deltaT = seconds(); 
    for (int i = 0; i < 100000; i++){ 
     sum = sumOfRandomNumbers(array, sizeOfArray); 
     if (i%10000 == 0) cout << i/1000 << " percent complete\n"; 
    } 
    deltaT = seconds() - deltaT; 
    cout << "\n\n\t\tRecursive method found sum to be " << sum; 
    cout << "\n\t\tThis recursive calc took " << deltaT << " seconds to run.\n"; 

} 

输出

Recursive Method 
0 percent complete 
10 percent complete 
20 percent complete 
30 percent complete 
40 percent complete 
50 percent complete 
60 percent complete 
70 percent complete 
80 percent complete 
90 percent complete 


       Recursive method found sum to be 2466.4 
       This recursive calc took 12.226 seconds to run. 

这里是完全更新,更新后的代码为编译。请注意奇怪的输出。我添加了粗体代码。如果不出现或很难看到的,这是改变

if (i%10000 == 0) cout << i/1000 << " percent complete\n"; 

if (i%10000 == 0) cout << "\n\t" << i/1000 << " percent complete\n"; 

............. .................................................. ............

#include <iostream> 
#include <stdlib.h> 
#include <time.h> 
using namespace std; 

double sumOfRandomNumbers(double arrayToFill[], int lengthOfArray){ 
    if(lengthOfArray == 0) return arrayToFill[lengthOfArray]; 
    return arrayToFill[lengthOfArray] + sumOfRandomNumbers(arrayToFill, lengthOfArray - 1); 
} 

double seconds(){return double(clock())/CLOCKS_PER_SEC;} 

int main(){ 

    int sizeOfArray = 5000; 
    double sum = 0.0, deltaT = 0.0, array[sizeOfArray]; 
    srand(time(NULL)); 

    for(int i = 0; i < sizeOfArray; i++) array[i] = double(rand())/double(RAND_MAX); 

    cout << "\nRecursive Method\n"; 
    deltaT = seconds(); 
    for (int i = 0; i < 100000; i++){ 
     sum = sumOfRandomNumbers(array, sizeOfArray); 
     if (i%10000 == 0) cout << "\n\t" << i/1000 << " percent complete\n"; 
    } 
    deltaT = seconds() - deltaT; 
    cout << "\n\n\t\tRecursive method found sum to be " << sum; 
    cout << "\n\t\tThis recursive calc took " << deltaT << " seconds to run.\n"; 

} 

输出

Recursive Method 

     0 percent complete 

     10 percent complete 

     20 percent complete 

     30 percent complete 

     40 percent complete 

     50 percent complete 

     60 percent complete 

     70 percent complete 

     80 percent complete 

     90 percent complete 


       Recursive method found sum to be 1.15021e+257 
       This recursive calc took 12.262 seconds to run. 

请注意我们是如何从非常合理的2466.4变为完全荒谬的1.15 x 10^257。没有做任何其他更改,即使经过几十次运行后,这些数字也是非常典型的,您上面看到的代码是编译和运行的确切代码。

+0

您知道'arrayToFill [lengthOfArray];'正在访问一个超过数组末尾的元素,因为索引从'0'开始。 – 2013-03-08 23:24:49

+5

帖子标题应与问题相关。另外,请只发布相关代码。没有人想读你的整个解决方案。当一个问题有一段代码时,我只需要寻找另一个答案。 – evanmcdonnal 2013-03-08 23:25:02

+2

这是一件好事,你标记了这个* sublimetext2 *,因为当代码不能按预期工作时,应该总是怀疑文本编辑器! – Praetorian 2013-03-08 23:27:14

回答

3

你有一个彻头彻尾的越界访问这里:

double sumOfRandomNumbers(double arrayToFill[], int lengthOfArray){ 
    if (lengthOfArray == 0) return arrayToFill[lengthOfArray]; 
    //        ^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    return arrayToFill[lengthOfArray] + 
    //  ^^^^^^^^^^^^^^^^^^^^^^^^^^ 
      sumOfRandomNumbers(arrayToFill, lengthOfArray - 1); 
} 

这将给Undefined Behavior在你的程序。当你的程序有未定义的行为时,一切都可能发生,包括有时程序seems to run just fine

+0

实际上两条线都是这样! – 2013-03-08 23:26:24

+0

@sftrabbit:哦,对!好赶:-) – 2013-03-08 23:27:11

+0

不错。我绝对错过了。我感谢你指出了这一点。不过,任何想法为什么\ n \ t似乎导致程序运行不同?在添加之前,程序多次没有问题。当我删除它们时,程序会恢复正常运行。 – 2013-03-08 23:42:39

0

您正在阅读无效内存(arrayToFill[lengthOfArray])。这是未定义的行为,所以它会变得棘手。也许你碰巧碰到了控制台的记忆,谁知道。不管确切的原因,这不是编译器中的一个错误。这是你的代码中的一个错误。

更新:

透露更多的细节,因为array是在栈上的最后一个项目,超越它的记忆往往是未使用和零初始化应用程序启动时(一些操作系统的安全性做;使例如,确保你不能读取其他程序可能遗留的旧密码)。

但如果另一个函数被调用具有本地变量,它将把在空间(一个值没有得到清除;你永远应该访问它,并且操作系统不一样,如果你在乎读你自己的密码)。

可能是因为cout的<<运算符有一些内部条件,有时它将第一个局部变量设置为非零值。也许第一个变量是bool beganWithNewline(做作!),它将您读取的元素的第一个字节设置为1,但是因为它是double的最重要的字节,所以这会产生一个巨大的值(好吧,因此它也必须设置一些东西在小数部分,但你看到的重点)。

+0

感谢您花时间回答! :) – 2013-03-08 23:44:53

+0

太棒了!也许这只是我的书呆子,但这个解释是非常酷的。 – 2013-03-09 00:19:40

相关问题