2

Was working on an assignment on a Mac machine and the code compiles and I get my expected output. As soon as I go to test it on the Ubuntu machines that the programs are run on for grading I get a Segmentation fault (core dumped) error message. I am really stumped and am looking for some tips for debugging why this occurs on the ubuntu machine (version 12.04) and not the mac machine (mavericks OS).

Edit: Running it through gdb I get the segmentation fault at

in getPath: line 28, if (path[position] == 0 && position == 0) {

My code is as follows:

#include <iostream>

using namespace std;

int minDistance(int distance[], bool shortestPath[]) {

    int min = 1000000000;
    int indexOfMin;

    for (int i = 0; i < 6; i++) {
        if (shortestPath[i] == false && distance[i] <= min) {
            min = distance[i]; 
            indexOfMin = i;
        }
    }

    return indexOfMin;
}

void getPath(int path[], int position) {
    cout << position + 1 << " <- ";

    // base case, we hit the end of the path
    if (path[position] == 0 && position == 0) {
        cout << path[position] + 1 << endl;
    }
    else if (path[position] == 0)
        cout << path[position] + 1 << endl;
    else {
        getPath(path, path[position]);
    }
}

void dijkstraAlgorithm(int weightedGraph[6][6], int sourceVertex) {
    int distance[6];     
    bool shortestPath[6]; 
    int path[6]; 

    for (int i = 0; i < 6; i++) {
        distance[i] = 1000000000; 
        shortestPath[i] = false;
    }

    distance[sourceVertex] = 0;

    for (int j = 0; j < 5; j++) {
        int min = minDistance(distance, shortestPath);
        shortestPath[min] = true;
        for (int k = 0; k < 6; k++) {
            if (!shortestPath[k] && weightedGraph[min][k] && distance[min] != 1000000000 && distance[min] + weightedGraph[min][k] < distance[k]) {
                distance[k] = weightedGraph[min][k] + distance[min];
                path[k] = min;
            }
        }
    }

    cout << "Distance       Path" << endl;
    for (int i = 0; i < 6; i++) {
        // dist[i] == 0 a formatting fix for first distance
        if (distance[i] == 0) {
            cout << distance[i] << ":            ";
            getPath(path, i);
        }
        else {
            cout << distance[i] << ":           ";
            getPath(path, i);
        }
    }
}

int main() {
    int weightedGraph[6][6] = {
        {0, 10, 0, 30, 100, 0},
        {0, 0, 50, 0, 0, 0},
        {0, 0, 0, 0, 10, 5},
        {0, 0, 20, 0, 0, 15},
        {0, 0, 0, 60, 0, 0},
        {0, 0, 0, 0, 0, 0}
    };

    dijkstraAlgorithm(weightedGraph, 0);

    return 0;
}

Note: I'm required to use the g++ compiler (version 4.6.4) on the Ubuntu environment

Josh Black
  • 999
  • 2
  • 8
  • 17
  • 1
    Smells Like Undefined behavior to me... Have you run it through a debugger to find where the segmentation fault occurs? – Sinkingpoint Dec 05 '13 at 01:35
  • Unfortunately not, the ubuntu computers I'm using are at my school and have no development IDE's installed. I also don't have permission to install any programs so I'm stuck with the terminal right now. Are there any debuggers that I'm not aware of that I could use to test this? – Josh Black Dec 05 '13 at 01:40
  • Compile it with debugging symbols and run it through gdb... – Sinkingpoint Dec 05 '13 at 01:41
  • Okay thanks! I got an error at line 28, if (path[position] == 0 && position == 0) { – Josh Black Dec 05 '13 at 01:45
  • I was able to run it in amazon AWS instances which have red hat. Worked fine. I think running it in debugger would be the best way forward. – Vikram Rao Dec 05 '13 at 01:46
  • @JoshBlack please share your findings on debugger here. Interesting to know why it happened. – Vikram Rao Dec 05 '13 at 01:47
  • @VikramRao I received the following from the debugger 'Program received signal SIGSEGV, Segmentation fault. 0x0000000000400a5b in getPath (path=0x7fffffffde60, position=6299112) at main.cpp:28 28 if (path[position] == 0 && position == 0) {' – Josh Black Dec 05 '13 at 01:50
  • And where do you initialize `path[]`? – Joe Z Dec 05 '13 at 01:52
  • @JoeZ I initialize it in dijkstraAlgorithm as int path[6]; – Josh Black Dec 05 '13 at 01:53
  • That's a declaration, but it's uninitialized and full of whatever garbage is on the stack. – Joe Z Dec 05 '13 at 02:01
  • If you can still run it on an AWS (or other) Linux then run your program using valgrind. – Drew MacInnis Dec 05 '13 at 02:02
  • @JoeZ OH, very true. Initializing it as an array of all 0's fixes the problem. Thank you very much! – Josh Black Dec 05 '13 at 02:07
  • I wonder why is it that it has to be initialized? – Vikram Rao Dec 05 '13 at 02:12
  • @VikramRao : Because there's no path leading into node 0, so the backtracking falls off the end there? – Joe Z Dec 05 '13 at 02:18
  • @JoeZ Right, i just saw the `getPath` is used in recursion and `path[position]` potentially can have garbage if not initialised. – Vikram Rao Dec 05 '13 at 02:24

2 Answers2

2

Running your sample code under valgrind shows these uninitialized read errors:

==25442== Conditional jump or move depends on uninitialised value(s)
==25442==    at 0x4008B2: getPath(int*, int) (crash.cpp:24)
==25442==    by 0x400B19: dijkstraAlgorithm(int (*) [6], int) (crash.cpp:62)
==25442==    by 0x400B9C: main (crash.cpp:81)

and:

==25442== Conditional jump or move depends on uninitialised value(s)
==25442==    at 0x4008F8: getPath(int*, int) (crash.cpp:27)
==25442==    by 0x400B19: dijkstraAlgorithm(int (*) [6], int) (crash.cpp:62)
==25442==    by 0x400B9C: main (crash.cpp:81)

among others.

Don't assume these arrays will be automatically initialized with zero (0):

int distance[6];
bool shortestPath[6];
int path[6];

Initialize these arrays and you'll eliminate some of the problems (at least).

Refer to Initialization of a normal array with one default value.

Updated: Why it works on the Mac is likely just happy coincidence, as mentioned in the answer to Turn off automatic initialization of variables in Xcode

Community
  • 1
  • 1
Drew MacInnis
  • 8,267
  • 1
  • 22
  • 18
  • Yes, this was my issue. Thank you very much! – Josh Black Dec 05 '13 at 02:11
  • Updated my answer to mention why it likely works for you on your Mac (under Xcode). – Drew MacInnis Dec 05 '13 at 02:13
  • By Xcode is initialising - do you mean gcc tools bundled with Xcode? This is not erroring out in Redhat too. So i don't think it has got anything to do with Xcode or OSX specific builds of gcc. Also that link of turning off automatic initialisation has no info on turning it off. – Vikram Rao Dec 05 '13 at 02:20
  • Sorry, my statement is misleading, I'll re-word it. Those arrays are allocated on the stack... so the particular values they happen to have isn't really defined... it could just be luck and quirks of OSX memory/stack management that has it working. – Drew MacInnis Dec 05 '13 at 02:22
  • @DrewMacInnis This is working fine in RedHat too. So i don't think it has anything to do with OSX – Vikram Rao Dec 05 '13 at 02:23
  • Are the Ubuntu and RHEL environments 32-bit or 64-bit? – Drew MacInnis Dec 05 '13 at 02:24
  • Bottom line is, the behaviour (contents) of uninitialized arrays is undefined. Don't rely on it. – Drew MacInnis Dec 05 '13 at 02:27
0

If you're doing something bad (invoking undefined behaviour), then an application can work on one OS and not on another. For C and C++ the list of things that can induce undefined behaviour is large... But in your case its probably an out-of-bounds memory access.

To debug it on linux I would run the application through valgrind, which will tell you when you make the first invalid access, (rather than the one that crashes your code - which may not be the first.).

If you're stuck on OS X I'd first run the code through the static analyser that is part of XCode. It will sometimes warn you about stupid accesses. Then after that I'd look at using the malloc debugging tools to help you narrow down the invalid access. "man malloc" will give you a list of the available environment variables.

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
  • There is no error on OSX. How can use of Xcode tools help debug the issue? – Vikram Rao Dec 05 '13 at 02:07
  • @VikramRao Static analysis tools don't need your application to crash, or even run. They analyse the flow through the code at compile-time and looks for invalid behaviour. – Michael Anderson Dec 05 '13 at 02:40