2012-03-01 15 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