2012-03-01 11 views
3

我已经追溯到一个函数应该返回浮点值介于20和100左右,但有时(10的1次)返回比这更高的值。当我在方法的最后一行的表达,这样存在的问题:在我的C++方法gremlins

return snap(baseNumber, targets) + (octave * NOTES_PER_OCTAVE); 

如果我存储在一个变量返回的值,然后再返回变量,问题消失:

float ret = snap(baseNumber, targets) + (octave * NOTES_PER_OCTAVE); 
return ret; 

下面是完整的方法:

static inline float octaveSnap(float number, std::vector<float>* targets){ 
    static const int NOTES_PER_OCTAVE = 12; 
    int octave = number/NOTES_PER_OCTAVE; 
    float baseNumber = number - (octave * NOTES_PER_OCTAVE); 
    float ret = snap(baseNumber, targets) + (octave * NOTES_PER_OCTAVE); 
    return ret; 
} 

和这里的 '捕捉':

// given a single value and a list of values (a scale), return the member of the list which is closest to the single value 
static inline float snap(float number, std::vector<float>* targets){ 
    float ret; 
    float leastDistance = -1; 
    for(int i = 0; i<targets->size(); i++){ 
     float distance = targets->at(i) - number; 
     if(distance < 0){ 
      distance = -distance; 
     } 
     if(leastDistance == -1){ 
      leastDistance = distance; 
     } 
     if(distance < leastDistance){ 
      leastDistance = distance; 
      ret = targets->at(i); 
     } 
    } 
    return ret; 
} 

我完全被这个困惑了。任何想法为什么第一个爆炸和第二个完美的作品?

+0

这看起来像我在程序中其他地方的内存损坏(例如缓冲区溢出)。 – 2012-03-01 14:12:44

+0

什么是方法签名? – cha0site 2012-03-01 14:12:54

+0

听起来像它与促销和/或RVO有关...我想你最好的选择是检查生成的程序集。 – 2012-03-01 14:13:07

回答

2

snap()本地变量ret从不初始化,所以如果输入矢量或者是零大小或者“found”元素是第一个,那么您的返回值是未指定的。

尝试修改快照是:

static inline float snap(float number, std::vector<float>* targets){ 
    float ret = 0; 
    float leastDistance = -1; 
    for(int i = 0; i<targets->size(); i++){ 
     float distance = targets->at(i) - number; 
     if(distance < 0){ 
      distance = -distance; 
     } 
     if(leastDistance == -1){ 
      leastDistance = distance; 
      ret = targets->at(i); 
     } 
     else if(distance < leastDistance){ 
      leastDistance = distance; 
      ret = targets->at(i); 
     } 
    } 
    return ret; 
} 

,看看是否能解决的事情。

编辑:我意识到这并不解决为什么添加一个临时变量似乎修复了原来的问题。未初始化的ret可能承担堆栈上留下的任何值:这当然是未指定的,并且系统/平台相关。但是,如果添加新的本地变量来存储snap()的结果,则会移动堆栈,使ret具有不同的位置,最有可能是不同的未初始化值。返回结果仍然是“错误的”,但由于未初始化的值为ret,它可能会出现“较少错误”。

+0

谢谢你谢谢你,谢谢你。我的代码中的gremlin是我!这个问题实际上并不是我没有初始化ret,而是当“found”元素是第一个元素时ret没有被设置。将distance 改为'distance <= leastDistance'修复了它。 – morgancodes 2012-03-01 16:10:48

4

我的心理调试的力量告诉我,当你使用的临时变量的问题只出现走开,要么你不小心做targets[<foo>]snap或者你使用它正确,但很少流失结束,返回垃圾。

编辑点评:

我要详细一点:targets指针vector所以用它[]将选择几个载体之一,从矢量不是元素。这就是说我无法理解你如何在这样一个指针上调用.at,所以我怀疑你程序中的代码不是你向我们展示的代码。

+0

有一个功能强大的心理调试器,它一定很棒!我确实在做'目标[]'内'快照'。我已经将其更改为'targets.at()'。这可能会使更好/更安全的C++风格,但不能解决我的错误。 temp变量的使用非常明显地改变了行为。我已经多次来回验证过,当我使用temp变量时,事情能够正常工作,而当我不使用时会失败。 – morgancodes 2012-03-01 14:42:38

+0

我搞砸了一些东西,但它并没有被弄糊涂指针是什么。我实际上是在'snap'内部做'targets->()',但是在(失败)尝试中写下targets.at()以避免混淆。 – morgancodes 2012-03-01 14:51:05

+0

如果你只通过一个'octaveSnap'调用与一个'targets'向量交互,你的函数签名应该是'static float octaveSnap(float number,std :: vector &targets)',或者'static float octaveSnap (float number,const std :: vector &targets)'如果函数不改变'targets'。而且,大多数编译器不再关注'inline'。 – 2012-03-01 14:58:00