Программа работает только с включением (без побочных эффектов) операторов cout?

Итак, я работал над проблемой 15 с веб-сайта Project Euler, и мой Решение работало отлично, пока я не решил удалить операторы cout, которые я использовал для отладки при написании кода. Мое решение работает путем создания треугольника Паскаля в одномерном массиве и поиска элемента, соответствующего количеству путей в решетке NxN, указанному пользователем. Вот моя программа:

#include <iostream>
using namespace std;

//Returns sum of first n natural numbers
int sumOfNaturals(const int n)
{
    int sum = 0;
    for (int i = 0; i <= n; i++)
    {
        sum += i;
    }
    return sum;
}

void latticePascal(const int x, const int y, int &size)
{
    int numRows = 0;
    int sum = sumOfNaturals(x + y + 1);
    numRows = x + y + 1;

    //Create array of size (sum of first x + y + 1 natural numbers) to hold all elements in P's T
    unsigned long long *pascalsTriangle = new unsigned long long[sum];
    size = sum;

    //Initialize all elements to 0
    for (int i = 0; i < sum; i++)
    {
        pascalsTriangle[i] = 0;
    }
    //Initialize top of P's T to 1
    pascalsTriangle[0] = 1;
    cout << "row 1:\n" << "pascalsTriangle[0] = " << 1 << "\n\n";  // <--------------------------------------------------------------------------------

    //Iterate once for each row of P's T that is going to be generated
    for (int i = 1; i <= numRows; i++)
    {
        int counter = 0;
        //Initialize end of current row of P's T to 1
        pascalsTriangle[sumOfNaturals(i + 1) - 1] = 1;
        cout << "row " << i + 1 << endl;   // <--------------------------------------------------------------------------------------------------------

        //Iterate once for each element of current row of P's T
        for (int j = sumOfNaturals(i); j < sumOfNaturals(i + 1); j++)
        {
            //Current element of P's T is not one of the row's ending 1s
            if (j != sumOfNaturals(i) && j != (sumOfNaturals(i + 1)) - 1)
            {
                pascalsTriangle[j] = pascalsTriangle[sumOfNaturals(i - 1) + counter] + pascalsTriangle[sumOfNaturals(i - 1) + counter + 1];
                cout << "pascalsTriangle[" << j << "] = " << pascalsTriangle[j] << '\n';   // <--------------------------------------------------------
                counter++;
            }
            //Current element of P's T is one of the row's ending 1s
            else
            {
                pascalsTriangle[j] = 1;
                cout << "pascalsTriangle[" << j << "] = " << pascalsTriangle[j] << '\n';  // <---------------------------------------------------------
            }
        }
        cout << endl;
    }

    cout << "Number of SE paths in a " << x << "x" << y << " lattice: " << pascalsTriangle[sumOfNaturals(x + y) + (((sumOfNaturals(x + y + 1) - 1) - sumOfNaturals(x + y)) / 2)] << endl;
    delete[] pascalsTriangle;
    return;
}

int main()
{
    int size = 0, dim1 = 0, dim2 = 0;

    cout << "Enter dimension 1 for lattice grid: ";
    cin >> dim1;
    cout << "Enter dimension 2 for lattice grid: ";
    cin >> dim2;
    latticePascal(dim1, dim2, size);

    return 0;
}

Операторы cout, которые, кажется, сохраняют мою программу, отмечены стрелками с комментариями. Кажется, это работает, пока включена любая из этих строк. Если удалить все эти операторы, то программа напечатает: "Число путей SE в " и затем зависнет на пару секунд перед завершением без печать ответа. Я хочу, чтобы эта программа была как можно более чистой и просто выводила ответ без необходимости печатать все содержимое треугольника, поэтому в текущем состоянии она не работает должным образом.


person philly b    schedule 04.08.2018    source источник
comment
Попробуйте включить все предупреждения и очистить все неопределенное поведение...   -  person user202729    schedule 04.08.2018
comment
Мой компилятор, похоже, не дает мне никаких предупреждений, я использую сообщество Visual Studio 2017. И я не уверен, где может происходить неопределенное поведение...   -  person philly b    schedule 04.08.2018
comment
Я взгляну! Спасибо за ссылку.   -  person philly b    schedule 04.08.2018


Ответы (2)


Существует большая вероятность того, что либо выражение для вычисления индекса массива, либо выражение для вычисления размера массива для распределения вызовет неопределенное поведение, например, переполнение стека.

Поскольку видимость этого неопределенного поведения для вас не определена, программа может работать так, как вы предполагали, или может делать что-то еще, что может объяснить, почему она работает с одним компилятором, а не с другим.

Вы можете использовать вектор с vector::resize() и vector::at() вместо массива с new и [], чтобы получить улучшенную информацию в случае, если программа прерывается до записи или сбрасывает весь свой вывод из-за недопустимый доступ к памяти.

Если проблема связана с использованием недопустимого индекса, тогда vector::at() вызовет исключение, которое вы не поймаете, и многие отладчики остановятся, когда найдут эту пару факторов вместе, и помогут вам проверить укажите в программе, где возникла проблема, и ключевые факты, такие как индекс, к которому вы пытались получить доступ, и содержимое переменных.

Обычно они показывают больше «фреймов стека», чем вы ожидаете, но некоторые из них являются внутренними деталями того, как система управляет неперехваченными исключениями, и вы должны ожидать, что отладчик поможет вам найти кадр стека, относящийся к вашей проблеме, чтобы вы могли проверить контекст того.

person codeshot    schedule 04.08.2018

Ваша программа хорошо работает с g++ в Linux:

$ g++ -o main pascal.cpp
$ ./main
Enter dimension 1 for lattice grid: 3
Enter dimension 2 for lattice grid: 4








Number of SE paths in a 3x4 lattice: 35

Должно быть что-то еще, поскольку ваши утверждения cout не имеют побочных эффектов. Вот идея, как это отладить: откройте 2 экземпляра Visual Studio, у одного будет версия без операторов cout, а у другого будет версия с ими. Просто выполните пошаговую отладку, чтобы найти первое различие между ними. Я предполагаю, что вы поймете, что операторы cout не имеют ничего общего с ошибкой.

person OrenIshShalom    schedule 04.08.2018
comment
Хм. Это странно... Я послушаюсь твоего совета и сделаю именно это! Спасибо за ответ. Думаю, мой первый шаг в следующий раз, когда я столкнусь с такой ошибкой, будет просто попробовать ее с другим компилятором. - person philly b; 04.08.2018