Search code examples
c++vectorpush-back

Execution is halting at push_back


The following for loop halts execution at the first cycle, and I have no clue why. I have figured out by placing couts in it that it stops at the push_back. It was working before, then I tried modifying it, then I did Ctrl-z to get it back to this state, and now it suddenly halts at push_back when it didn't seem to before. What is going on?

#include <iostream>
#include <vector>
using namespace std;
void decode(int[], int, int[][2]);
void displayArray(int[], int);

int main()
{
    const int SIZE = 12;
    int test[SIZE-2] = {3,9,1,4,8,0,11,5,1,8};
    int edgeList[SIZE-1][2];
    for (int i = 0; i < SIZE -1; i++)
    {
        edgeList[i][0] = -1;
        edgeList[i][1] = -1;
    }
    decode(test, SIZE, edgeList);
    return 0;
}

void decode(int inputString[], int size, int edgeList[][2])
{
    int** arrayC = new int*[size - 2];
    for(int i = 0; i < size - 2; i++)
        arrayC[i] = new int[2];
    for (int i = 0; i < size -2 ; i++)
    {
        arrayC[i][0] = i+1;
        arrayC[i][1] = inputString[i];
    }

    for (int i = 0; i < size - 2; i++)
    {
        displayArray(arrayC[i], 2);
    }

    for (int i = 0; i < size - 1; i++)
    {
        vector<int> currentCycle;
        int *visited = new int[size - 2];
        for(int j = 0; j < size - 1; j++)
        {
            visited[j] = 0;
        }
        bool repeat = false;
        int currentIndex = i;
        while(!repeat)
        {
            int curElem = arrayC[currentIndex][0];
            if (!visited[curElem] && curElem != 0 && curElem != size - 1)
            {
                cout << curElem << endl;
                currentCycle.emplace_back(curElem);
                visited[curElem] = 1;
            }
            else
            {
                repeat = true;
            }
            currentIndex = arrayC[currentIndex][1] - 1;
            if (currentIndex == -1 || currentIndex == size -2)
            {
                repeat = true;
                currentCycle.push_back(-1);
            }
        }
        for (int i = 0; i < currentCycle.size(); i++)
            cout << currentCycle[i] << " ";
        cout << endl;
        delete visited;
    }
}

void displayArray(int array[], int size)
{
    for (int i = 0; i < size; i++)
    {
        cout << array[i] << " ";
    }
    cout << endl;
}

Solution

  •     int *visited = new int[size - 2];
    

    size is 12. This allocates an array of 10 ints: visited[0] through visited[9].

        for(int j = 0; j < size - 1; j++)
    

    This for loop iterates with j from 0 to 10. size - 1 is 11. The last value of j in this loop, therefore, is 10.

            visited[j] = 0;
    

    This will, eventually, attempt to set visited[10] to 0.

    Fail. The visited array is too small. Only visited[0] through visited[9] are valid. This results in memory corruption and undefined behavior.

    This may or may not be the only bug in the shown code. This is the first memory access violation that was easily found using valgrind, a wonderful static memory analysis tool, which stopped this program's execution right when the memory corruption occured, allowing me to break into the program with my debugger, inspect the values of all variables, and easily identify what the problem is.

    It's worthwhile to spend some time learning how to use debugging and diagnostic tools, like these ones. They do really help you find bugs in your own code, very quickly.

    The overall purpose of the code is not immediately clear, so it's not obvious what the right fix should be, so I just stopped after finding the first showstopper. It's possible that after fixing this, as I briefly mentioned, there might be other, similar, problems. If so, you should be able to find them the same way I did, with some help from some useful tools, which you probably have, already.