使用-O2编译时,程序会跳过赋值

时间:2015-06-02 01:28:07

标签: c++ optimization

我正在编写一个代码来解决编程挑战,但是当我提交代码时,它给出了运行时错误。有人告诉我尝试使用-O2编译它,看看我是否能找到问题。

事实证明发生了令人毛骨悚然的事情:执行时,优化版本只是跳过一个关键变量的分配!

代码如下:

#include <iostream>
#include <cmath>

using namespace std;

const unsigned int primos[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997};
const unsigned int nprimos = 168;

struct numprim {
    unsigned int num;
    unsigned int qtdd;
};

numprim numeros[1000];

bool
compare(numprim &a, numprim &b) {
    return (a.qtdd < b.qtdd || (a.qtdd == b.qtdd && a.num > b.num));
}

void quickSort(int esquerda, int direita)
{
    int i, j;
    numprim x, y;
    i = esquerda;
    j = direita;
    x = numeros[(esquerda + direita) / 2];

    while(i <= j)
    {
        while(compare(numeros[i], x) && i < direita)
        {
            i++;
        }
        while(compare(x, numeros[j]) && j > esquerda)
        {
            j--;
        }
        if(i <= j)
        {
            y = numeros[i];
            numeros[i] = numeros[j];
            numeros[j] = y;
            i++;
            j--;
        }
    }
    if(j > esquerda)
    {
        quickSort(esquerda, j);
    }
    if(i < direita)
    {
        quickSort(i, direita);
    }
}


int main() {
    unsigned int i, j;
    unsigned int tmp, num;

    for(i = 0; i < 1000; ++i) {
        numeros[i].qtdd = 1;
        numeros[i].num = num = i+1;

        // TODO: Verificar se ha como sair pela primeira condicao, e o que fazer
        j = 0;
        while((j < nprimos) && (num % primos[j] > 0))
            ++j;

        for(tmp = 0; num % primos[j] == 0; ++tmp)
            num /= primos[j];

        numeros[i].qtdd = (tmp+1)*numeros[num-1].qtdd;
    }

    quickSort(0, 999);

    cin >> tmp;
    for(i = 1; i <= tmp; ++i) {
        cin >> num;

        cout << "Case " << i << ": " << numeros[num-1].num << endl;
    }

    return 0;
}

我使用命令g++ -O2 -g3 -Wall -Wextra -o ordem ordem.cpp

编译的g ++ 4.9.2

当在gdb中运行时,奇怪的是,只是在&#34; for&#34;的第一次迭代中(主要功能,num获得的值不同于numeros[i].num字段。我还尝试移动内容,重命名内容以及其他绝望措施,但没有一个有效。

我根本无法理解是什么导致了这种行为。有人请帮帮我吗?我打算把这段代码展示给我的学生......

1 个答案:

答案 0 :(得分:5)

group(2)

while((j < nprimos) && (num % primos[j] > 0)) ++j; 循环终止的一种方法是while(例如j == nprimos时,因此i == 0;显然1不能被任何素数整除。)

在这种情况下,后续num == 1循环中对primos[j]的访问权限将超出范围。