我的c ++方法中的gremlins

时间:2012-03-01 14:09:10

标签: c++

我已经将一个错误追溯到一个函数,该函数应该返回20到100左右的浮点值,但有时(10次中的1次)返回的值远高于此值。当我在方法的最后一行中有一个表达式时会出现问题,如下所示:

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;
}

这里是'snap':

    // 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;
}

我对此完全感到困惑。知道为什么第一次爆炸和第二次完美运作?

2 个答案:

答案 0 :(得分:4)

我的通灵调试能力告诉我,当你使用临时变量时,问题似乎只会消失,而你在targets[<foo>]内意外地做snap或者你正确使用它但很少运行最后,返回垃圾。

编辑评论:

我应该详细说明:targets指针vector所以使用[]就可以选择其中一个向量,而不是来自向量。那说我无法理解你如何在这样的指针上调用.at,所以我怀疑你程序中的代码不是你向我们展示的代码。

答案 1 :(得分:2)

snap()中,局部变量ret永远不会被初始化,所以如果输入向量是零大小的,或者#34;找到&#34; element是第一个,那么你的返回值是未指定的。

尝试将snap修改为:

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具有不同的位置,最可能是不同的未初始化值。返回结果仍然是错误的&#34;但它可能只是出现'#34;较少的错误&#34;由于任何未初始化的值ret都有。