std::vector and memory error when resizing - c++

I have a structure defined like this:
struct Edge
{
int u, v; // vertices
Edge() { }
Edge(int u, int v)
{
this->u = u;
this->v = v;
}
};
and a class field defined like
vector<Edge> solution;
In one of the methods I'm creating new Edges and pushing them into the vector like this (a huge simplification of my real code, but the problem still exists):
solution.push_back(Edge(1, 2));
solution.push_back(Edge(3, 4));
solution.push_back(Edge(5, 6));
solution.push_back(Edge(7, 8));
solution.push_back(Edge(9, 10));
solution.push_back(Edge(11, 12));
solution.push_back(Edge(13, 14)); // adding 7th element; the problem occurs here
When the last push_back is executing, I'm getting an error window in Visual Studio's debug mode
[AppName] has triggered a breakpoint.
and the debugger goes to malloc.c, to the end of _heap_alloc function. Before this 7th line, the vector seems to work properly. I can see all the elements in the debugger. It seems that the vector has a problem reallocating itself (expanding its size).
What's interesting, if I put this before all the pushing back:
solution.reserve(7);
, the 7th edge is added properly. What's even more interesting, trying to reserve space for more than 22 elements also causes the mentioned error.
What am I doing wrong? How can I debug it? The rest of the application doesn't use so much memory, so I can't believe the heap is full.
More code, on request. It's a rather sloppy implementation of 2-approximation algorithm for Metric Travelling Salesman's Problem. It first creates a minimum spanning tree, then adds vertices (just indices) to the partialSolution vector in the DFS order.
void ApproxTSPSolver::Solve()
{
// creating a incidence matrix
SquareMatrix<float> graph(noOfPoints);
for (int r=0; r<noOfPoints; r++)
{
for (int c=0; c<noOfPoints; c++)
{
if (r == c)
graph.SetValue(r, c, MAX);
else
graph.SetValue(r, c, points[r].distance(points[c]));
}
}
// finding a minimum spanning tree
spanningTree = SquareMatrix<bool>(noOfPoints);
// zeroeing the matrix
for (int r=0; r<noOfPoints; r++)
for (int c=0; c<noOfPoints; c++)
spanningTree.SetValue(r, c, false);
bool* selected = new bool[noOfPoints];
memset(selected, 0, noOfPoints*sizeof(bool));
selected[0] = true; // the first point is initially selected
float min;
int minR, minC;
for (int i=0; i<noOfPoints - 1; i++)
{
min = MAX;
for (int r=0; r<noOfPoints; r++)
{
if (selected[r] == false)
continue;
for (int c=0; c<noOfPoints; c++)
{
if (selected[c] == false && graph.GetValue(r, c) < min)
{
min = graph.GetValue(r, c);
minR = r;
minC = c;
}
}
}
selected[minC] = true;
spanningTree.SetValue(minR, minC, true);
}
delete[] selected;
// traversing the tree
DFS(0);
minSol = 0.0f;
// rewriting the solution to the solver's solution field
for (int i=0; i<noOfPoints - 1; i++)
{
solution.push_back(Edge(partialSolution[i], partialSolution[i + 1]));
minSol += points[partialSolution[i]].distance(points[partialSolution[i + 1]]);
}
solution.push_back(Edge(partialSolution[noOfPoints - 1], partialSolution[0]));
minSol += points[partialSolution[noOfPoints - 1]].distance(points[partialSolution[0]]);
cout << endl << minSol << endl;
solved = true;
}
void ApproxTSPSolver::DFS(int vertex)
{
bool isPresent = std::find(partialSolution.begin(), partialSolution.end(), vertex)
!= partialSolution.end();
if (isPresent == false)
partialSolution.push_back(vertex); // if I comment out this line, the error doesn't occur
for (int i=0; i<spanningTree.GetSize(); i++)
{
if (spanningTree.GetValue(vertex, i) == true)
DFS(i);
}
}
class ApproxTSPSolver : public TSPSolver
{
vector<int> partialSolution;
SquareMatrix<bool> spanningTree;
void DFS(int vertex);
public:
void Solve() override;
};
from main.cpp:
TSPSolver* solver;
string inputFilePath, outputFilePath;
// parsing arguments
if (ArgParser::CmdOptionExists(argv, argv + argc, "/a"))
{
solver = new ApproxTSPSolver();
}
else if (ArgParser::CmdOptionExists(argv, argv + argc, "/b"))
{
solver = new BruteForceTSPSolver();
}
else
{
solver = new BranchAndBoundTSPSolver();
}
inputFilePath = ArgParser::GetCmdOption(argv, argv + argc, "/i");
outputFilePath = ArgParser::GetCmdOption(argv, argv + argc, "/s");
solver->LoadFromFile(inputFilePath);
Timer timer;
timer.start();
solver->Solve();
timer.stop();
cout << timer.getElapsedTime();
A part of TSPSolver.c:
TSPSolver::TSPSolver()
{
points = NULL;
solved = false;
}
TSPSolver::~TSPSolver()
{
if (points)
delete[] points;
}
void TSPSolver::LoadFromFile(string path)
{
ifstream input(path);
string line;
int nodeID;
float coordX, coordY;
bool coords = false;
minX = numeric_limits<float>::max();
maxX = numeric_limits<float>::min();
minY = numeric_limits<float>::max();
maxY = numeric_limits<float>::min();
while (input.good())
{
if (coords == false)
{
getline(input, line);
if (line == "NODE_COORD_SECTION")
{
coords = true;
}
else if (line.find("DIMENSION") != string::npos)
{
int colonPos = line.find_last_of(":");
noOfPoints = stoi(line.substr(colonPos + 1));
#ifdef _DEBUG
cout << noOfPoints << " points" << endl;
#endif
// allocating memory for this amount of points
points = new Point[noOfPoints];
}
}
else
{
input >> nodeID >> coordX >> coordY;
points[nodeID - 1].X = coordX;
points[nodeID - 1].Y = coordY;
minX = min(minX, coordX);
maxX = max(maxX, coordX);
minY = min(minY, coordY);
maxY = max(maxY, coordY);
if (nodeID == noOfPoints)
{
break;
}
}
}
input.close();
}

This is rather a comment then an answer, but the space is too limited.
If you are on windows, try Microsoft Application Verifier. It might detect wrong memory access.
Another way of detecting such access is to reseve empty char arrays initialized to 0.
Open your class where the vector is declared and declare a char array of let's say 64 chars before and after your vector and initialize them to 0!.
Then break into your vector code, where the error is generated and check the contents of those padding arrays. If they are filled, somebody writes more that it should.
A way to locate the "malicious" access (at least in VC++) is to set a data breakpoint writing in your padding arrays and check the callstack then.

You may be doing out-of-bounds accesses on points in various places, e.g. this one:
input >> nodeID >> coordX >> coordY;
points[nodeID - 1].X = coordX;
What if input failed, or the value is out of range?
I would suggest removing all uses of new and delete and []from your code; e.g. assuming points is int *points; then replace it with std::vector<int> points. Change all [] accesses to be .at() and catch exceptions. Disable copying on all classes that don't have correct copy semantics.
Then you can be more certain that it is not a memory allocation error, copying error, or out-of-bounds access (which are strong candidates for explaining your symptoms).
This would also fix the problem that TSPSolver currently does not have correct copy semantics.
It would be very useful to make a SSCCE. You mention that there is "a lot of input", try reducing the input as small as you can but still have the problem occur. An SSCCE can include input data so long as it is a manageable size that you can post. Currently you show too much code but not enough, as they say. The problem is still lurking somewhere you haven't posted yet.

Related

Shortest path with file as input

I'm creating a graph taking a file as input and I want to calculate the shortest path, to do so I used SPF algorithm. I have a few file I can use to see if it works, and here comes the problem because it works until I try it with the biggest one (which has over 1 million vertex and 2 million edges), considering that the second for dimension has about 700k vertex and 100 million edges and with it it works just fine, what do you think the problem is? I just need some hint I really can't figure it out!
Please be patient with me, I'm new in this comunity and to coding in general, I'm just trying to learn and understand things properly...
It's returning error 3221225725
// Function to compute the SPF algorithm
void shortestPathFaster(int S, int V)
{
// Create array d to store shortest distance
int d[V + 1];
// Boolean array to check if vertex
// is present in queue or not
bool inQueue[V + 1] = { false };
// Initialize the distance from source to
// other vertex as INT_MAX(infinite)
for (int i = 0; i <= V; i++) {
d[i] = INT_MAX;
}
d[S] = 0;
queue<int> q;
q.push(S);
inQueue[S] = true;
while (!q.empty()) {
// Take the front vertex from Queue
int u = q.front();
q.pop();
inQueue[u] = false;
// Relaxing all the adjacent edges of
// vertex taken from the Queue
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].first;
int weight = graph[u][i].second;
if (d[v] > d[u] + weight) {
d[v] = d[u] + weight;
// Check if vertex v is in Queue or not
// if not then push it into the Queue
if (!inQueue[v]) {
q.push(v);
inQueue[v] = true;
}
}
}
}
// Print the result
print_distance(d, V);
}
The problem is most likely here:
int d[V + 1];
Firstly, variable length arrays are non-standard. Secondly, if V is large you will overflow the stack.
Solution: replace this with std::vector. bool inQueue[V + 1] should be treated similarly.
Also, replace char buffer[BUFFER_SIZE]; with std::string. You'll be glad you did.

graph rerouting algorithm hacker rank

I have tried to solve the problem Rerouting at hacker rank. I am posting here for help as competition is over.
https://www.hackerrank.com/contests/hack-the-interview-v-asia-pacific/challenges/rerouting
I have tried to solve problem using Strong connected components, but test cases failed. I can understand we have to remove cycles. But I stuck how to approach problem. Below is solution i have written. I am looking for guidence how to move forward so that i can apply my knowledge future based on mistakes i made here. Thanks for your time and help
int getMinConnectionChange(vector<int> connection) {
// Idea: Get number of strongly connected components.
int numberOfVertices = connection.size();
for(int idx = 0; idx < numberOfVertices; idx++) {
cout << idx+1 <<":"<< connection[idx] << endl;
}
stack<int> stkVertices;
map<int, bool> mpVertexVisited; //is vertex visited.think this as a chalk mark for nodes visited.
int numOFSCCs = 0;
int currTime = 1;
for (int vertexId = 0; vertexId < numberOfVertices; vertexId++) {
// check if node is already visited.
if (mpVertexVisited.find(vertexId+1) == mpVertexVisited.end()) {
numOFSCCs++;
mpVertexVisited.insert(make_pair(vertexId+1, true));
stkVertices.push(vertexId+1);
currTime++;
while (!stkVertices.empty()) {
int iCurrentVertex = stkVertices.top();
stkVertices.pop();
// get adjacent vertices. In this excercise we have only one neighbour. i.e., edge
int neighbourVertexId = connection[iCurrentVertex-1];
// if vertex is already visisted, don't insert in to stack.
if (mpVertexVisited.find(neighbourVertexId) != mpVertexVisited.end()) {
continue;
}
mpVertexVisited.insert(make_pair(neighbourVertexId, true));
stkVertices.push(neighbourVertexId);
} // while loop
} // if condition m_mapVrtxTimes.find(*itr) == m_mapVrtxTimes.end()
} // for loop of vertices
return numOFSCCs - 1;
}
This is a problem that I just solved and would like to share the solution.
The problem can be solved with union-find.
Two main observation:
The number of edges that has to be changed is the number of components - 1 (not necessarily strongly connected) Thus, union-find is handy here for finding the number of components
Second observation is that some component doesn't have terminating node, consider 1<->2, in other words, a cycle exist. We can detect whether there exists a terminating node if some node doesn't have an outgoing edge.
If all components have a cycle, it means that we need to change every component instead of a number of components - 1. This is to make it such that the graph will have a terminating point.
Code:
struct UF {
vector<int> p, rank, size;
int cnt;
UF(int N) {
p = rank = size = vector<int>(N, 1);
for (int i = 0; i < N; i++) p[i] = i;
cnt = N;
}
int find(int i) {
return p[i] == i ? i : p[i] = find(p[i]);
}
bool connected(int i, int j) {
return find(i) == find(j);
}
void join(int i, int j) {
if (connected(i, j)) return;
int x = find(i), y = find(j);
cnt--;
if (rank[x] > rank[y]) {
p[y] = x;
size[x] += size[y];
} else {
p[x] = y;
size[y] += size[x];
if (rank[x] == rank[y]) rank[y]++;
}
}
};
int getMinConnectionChange(vector<int> connection) {
int nonCycle = 0;
int n = connection.size();
UF uf(n);
for(int i=0;i<n;i++) {
int to = connection[i] - 1;
if(to == i) nonCycle++;
else uf.join(i, to);
}
int components = uf.cnt;
int countCycle = uf.cnt - nonCycle;
int res = components - 1;
if(countCycle == components) res++; // all components have cycle
return res;
}
TL;DR: you can view this as looking for a minimal spanning arborescence problem.
More precisely, add a node for each server, and another one called "Terminate".
Make a complete graph (each node is linked to every other one) and set as cost 0 for the edges corresponding to your input, 1 for the other ones.
You can use for example Edmond's algorithm to solve this.

Shortest path given beginning and end of a weighted graph

I have to read in a file to create a weighted graph. The shortest path must be found using input from the file. File will be structured as first line = numVertices and every line below that has 3 numbers given as : 0 1 2 where 0 is start of an edge, 1 is the end of the edge, and 2 is the weight. I've tried implementing an adjacency matrix when creating my graph but have had no luck. Any suggestions would be greatly appreciated.
Have tried restructuring the way I read in my file and have also tried adjusting my findShortestPath function.
void createGraph(string file_name) //Function to create a graph based on a file, whose name is file_name.
{
ifstream f(file_name);
if (f.fail())
{
return;
}
string line;
getline(f, line);
int num = stoi(line);
numVertices = num;
int data[50][50];
string line2;
int num1 = 0, num2 = 0, num3 = 0;
while (!f.eof())
{
f >> num1;
f >> num2;
f >> line2;
num3 = stoi(line2);
data[num1][num2] = num3;
}
}
//////////////////shortest path function
string findShortestPath(int start, int end)
{
int data[numVertices][numVertices];
int dist[numVertices];
bool sptSet[numVertices];
int parent[numVertices];
for (int i = 0; i < numVertices; i++)
{
parent[0] = -1;
dist[i] = INT_MAX;
sptSet[i] = false;
}
dist[start] = 0;
for (int count = 0; count < numVertices - 1; count++)
{
int u = minDistance(dist, sptSet);
sptSet[u] = true;
if (sptSet[u] == end)
break;
for (int v = 0; v < numVertices; v++)
if (!sptSet[v] && data[u][v] && dist[u] + data[u][v] < dist[v])
{
parent[numVertices] = end;
dist[v] = dist[u] + data[u][v];
}
}
printSolution(parent);
Output is not outputting shortest path and is printing random numbers.
In your findShortestPath function data[numVertices][numVertices] is not the same as the data variable in your createGraph function.
Look at this https://www.geeksforgeeks.org/scope-of-variables-in-c/ or try finding other sources on scope of variables.
In your function findShortestPath you have declared a local array called data, which is supposed to store the adjacency matrix data. However, you have never written any data into it! Consider passing the matrix as a function argument. Your function signature should look something like this:
findShortestPath(int** data, int numVertices, int start, int end)
Also, avoid using VLA as it is not part of the standard. Consider creating a two dimensional array on the heap using new. (and don't forget to do delete[] after you are done!)
Or you can use std::vector<std::vector<int>>, if you don't want to manage your array's lifetime manually.

c++ MFC slow runtime with 2D vector

I recently finished writing what I consider my "main.cpp" code in a Win32 Console project. It builds the solution perfectly and the external release version runs and completes within like 30 seconds, which is fast for the number of calculations it does.
When I use my MFC built UI made with just 1 standard dialog box for some simple float inputs, the program that ran fine by itself gets hung up when it has to create and calculate some 2D-vectors.
std::mt19937 generator3(time(0));
static uniform_01<std::mt19937> dist3(generator3);
std::vector<int> e_scatter;
for (int i = 0; i <= n; i++)
{
if (dist3() >= perc_e)
{
e_scatter.push_back(1);
// std::cout << e_scatter[i] << '\n';
// system("pause");
}
else
{
e_scatter.push_back(0);
// std::cout << e_scatter[i] << '\n';
// system("pause");
}
}
string fileName_escatter = "escatter.dat";
FILE* dout4 = fopen(fileName_escatter.c_str(), "w");
for (int i = 0; i <= n; i++)
{
fprintf(dout4, "%d", e_scatter[i]);
fprintf(dout4, "\n");
// fprintf(dout2, "%f", e_scatter[i]);
// fprintf(dout2, "\n");
};
fclose(dout4);
std::vector<vector<float>> electron;
// std::vector<float> angle;
**randutils::mt19937_rng rng2;
std::vector<float> rand_scatter;
for (int i = 0; i <= n; i++)
{
std::vector<float> w;
electron.push_back(w);
rand_scatter.push_back(rng2.uniform(0.0, 1.0));
for (int j = 0; j <= 2000; j++)
{
if (e_scatter[i] == 0)
{
electron[i].push_back(linspace[j] * (cos((rand_scatter[i] * 90) * (PI / 180))));
//electron[i][j] == abs(electron[i][j]);
}
else
{
electron[i].push_back(linspace[j]);
};
};
};**
More specifically it does not get past a specific for loop and I am forced to close it. I've let it run for 20 minutes to see if it was just computing things slower, but still got 0 output from it. I am not that great at the debugging part of code when I have this GUI from MFC since I dont have the console popping up.
Is there something that I am missing when I try to use MFC for the gui and large 2D vectors?
The first loop calculates and spits out an output file 'escatter.dat' after its finished but the second set of loops never finishes and the memory usage keeps ramping up.
linspace[i] is calculated before all of this code and is just a vector of 2001 numbers that it uses to populate the std::vector> electron vector in the double for loops.
Ive included this http://pastebin.com/i8A7t38K link to the MFC part of the code that I was using to not make this post really long to read.
Thank you.
I agree that the debugging checks are the major problem.
But if your program is running 30 seconds, n must be big.
You may consider optimizing your code for reducing memory allocations, by preallocating memory using vector::reserve;
std::vector<vector<float>> electron;
// std::vector<float> angle;
**randutils::mt19937_rng rng2;
std::vector<float> rand_scatter;
electron.reserve(n+1); // worth for big n
rand_scatter.reserve(n+1); // worth for big n
for (int i = 0; i <= n; i++)
{
std::vector<float> w;
electron.push_back(w);
rand_scatter.push_back(rng2.uniform(0.0, 1.0));
electron[i].reserve(2000+1); // really worth for big n
for (int j = 0; j <= 2000; j++)
{
if (e_scatter[i] == 0)
{
electron[i].push_back(linspace[j] * (cos((rand_scatter[i] * 90) * (PI / 180))));
//electron[i][j] == abs(electron[i][j]);
}
else
{
electron[i].push_back(linspace[j]);
};
};
};**
or rewrite by not using push_back (since you know all sizes)
std::vector<vector<float>> electron(n+1);
// std::vector<float> angle;
**randutils::mt19937_rng rng2;
std::vector<float> rand_scatter(n+1);
for (int i = 0; i <= n; i++)
{
std::vector<float>& w=electron[i];
w.reserve(2000+1);
float r=rng2.uniform(0.0, 1.0);
rand_scatter[i]=r;
for (int j = 0; j <= 2000; j++)
{
float f;
if (e_scatter[i] == 0)
{
f=linspace[j] * (cos((r * 90) * (PI / 180)));
// f=abs(f);
}
else
{
f=linspace[j];
};
w[j]=f;
};
};**
After that runtime might decrease to at most few seconds.
Another optimization
string fileName_escatter = "escatter.dat";
FILE* dout4 = fopen(fileName_escatter.c_str(), "w");
for (int i = 0; i <= n; i++)
{
fprintf(dout4, "%d\n", e_scatter[i]); // save one method call
// fprintf(dout2, "%f\n", e_scatter[i]);
};
fclose(dout4);
BTW: ofstream is the stl-way of writing files, like
ofstream dout4("escatter.dat", std::ofstream::out);
for (int i = 0; i <= n; i++)
{
dout4 << e_scatter[i] << std::endl;
};
dout4.close();

Bug in selection sort loop

I need to make a program that will accept a input file of numbers(integer.txt) which will be sorted one number per line, into a vector, then use a selection sort algorithm to sort the numbers in descending order and write them to the output file (sorted.txt). I'm quite sure something is wrong in my selectionSort() function that is causing the loop not to get the right values, because after tested with cout I get vastly improper output. I'm sure it's a beginning programmer's goof.
vector<string> getNumbers()
{
vector<string> numberList;
ifstream inputFile ("integer.txt");
string pushToVector;
while (inputFile >> pushToVector)
{
numberList.push_back(pushToVector);
}
return numberList;
}
vector<string> selectionSort()
{
vector<string> showNumbers = getNumbers();
int vectorMax = showNumbers.size();
int vectorRange = (showNumbers.size() - 1);
int i, j, iMin;
for (j = 0; j < vectorMax; j++)
{
iMin = j;
for( i = j; i < vectorMax; i++)
{
if(showNumbers[i] < showNumbers[iMin])
{
iMin = i;
}
}
if (iMin != j)
{
showNumbers[j] = showNumbers [iMin];
}
}
return showNumbers;
}
void vectorToFile()
{
vector<string> sortedVector = selectionSort();
int vectorSize = sortedVector.size();
ofstream writeTo;
writeTo.open("sorted.txt");
int i = 0;
while (writeTo.is_open())
{
while (i < vectorSize)
{
writeTo << sortedVector[i] << endl;
i += 1;
}
writeTo.close();
}
return;
}
int main()
{
vectorToFile();
}
vectorRange defined but not used.
In your selectionSort(), the only command that changes the vector is:
showNumbers[j] = showNumbers [iMin];
Every time control reaches that line, you overwrite an element of the vector.
You must learn to swap two values, before you even think about sorting a vector.
Also, your functions are over-coupled. If all you want to fix is selectionSort, then you should be able to post that plus a main that calls it with some test data and displays the result, but no, your functions all call each other. Learn to decouple.
Also your variable names are awful.