AlexML
AlexML

Reputation: 33

C++ exception thrown

I am learning C++ and have lost quite some time trying to solve to understand the reason of the error i am getting. When i run the code below i am getting an Exception thrown. It happens when the program ends, so i believe it's related to the Edge pointer:

#include <iostream>
#include <vector>
#include <map>

using namespace std;


struct Edge {
    int src, dest;
};

class Graph {
    
public:
    int V, E;
    Edge *edge = new Edge[E * sizeof(Edge)];
    Graph(int Ver, int Edg);
};

Graph::Graph(int Ver, int Edg) {
    V = Ver;
    E = Edg;
}


Graph* createGraph(int V, int E) {

    Graph* graph = new Graph(V,E);
    return graph;
}

int find(int* parents, int val) {
    if (parents[val] == -1)
        return val;
    return find(parents, parents[val]);
}

void Union(int *parents, int x, int y) {
    parents[x] = y;
}


int isCycle(Graph* graph) {

    int* parents = new int[graph->V * sizeof(int)];

    memset(parents, -1, graph->V * sizeof(int));

    for (int i = 0; i < graph->E; i++) {
        int x = find(parents, graph->edge[i].src);
        int y = find(parents, graph->edge[i].dest);

        if (x == y) {
            return 1;
        };

        Union(parents, x, y);
    }


    return 0;
}



int main()
{

    int V = 9, E = 8;
    Graph* graph = createGraph(V, E);


    graph->edge[0].src = 0;
    graph->edge[0].dest = 1;

    graph->edge[6].src = 0;
    graph->edge[6].dest = 6;

    graph->edge[5].src = 0;
    graph->edge[5].dest = 7;

    graph->edge[1].src = 1;
    graph->edge[1].dest = 2;

    graph->edge[2].src = 3;
    graph->edge[2].dest = 2;

    graph->edge[3].src = 4;
    graph->edge[3].dest = 3;

    graph->edge[4].src = 4;
    graph->edge[4].dest = 5;

    graph->edge[7].src = 5;
    graph->edge[7].dest = 7;

    if (isCycle(graph))
        cout << "graph contains cycle";
    else
        cout << "graph doesn't contain cycle";

    return 0;
}

I started learning C++ only few months ago, can somebody help me to understand why I am getting that exception?

Upvotes: 2

Views: 232

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118425

 Edge *edge = new Edge[E * sizeof(Edge)];

Unless E is initialized, this multiplies an uninitalized variable by sizeof(Edge) (which is also wrong on its face value as well, but we'll get to it later). This is undefined behavior.

Graph::Graph(int Ver, int Edg) {
    V = Ver;
    E = Edg;
}

This isn't good enough. The default values of class members, if specified, are used to initialize them before the constructor's body starts running.

The proper way to do this is to use the constructor's initialization section:

Graph::Graph(int Ver, int Edg) : V{Ver}, E{Edg}  { }

This initializes V and E first.

Now consider:

Edge *edge = new Edge[E * sizeof(Edge)];

So here, E is now initialized, fixing one problem. But this is still incorrect. It's clear, based on the rest of the code, that this should really be:

Edge *edge = new Edge[E];

In C++, when you wish to declare an array of, say, 4 integers, all you have to do is declare:

int n[4];

The compiler takes care of multiplying 4 by however many bytes it takes to hold an int. The same thing is true for the new statement. If your goal is to construct an array of #E Edges, that would be, unsurprisingly: new Edge[E]. This same mistake occurs several times in the shown code.

Upvotes: 4

Related Questions