free(): invalid pointer error on vector.push_back() - c++

My code gives me free(): invalid pointer error (I don't call free, so my understanding is that it has something to do with how vectors operate internally). I am beginner to C++, so though I checked other answers to similar questions, I fail to see what exactly causes the issue.
I have a grid graph (i.e. vertex is connected with its 4-neighbors). Some vertices hold a special value, which is written done in a file in a form:
row columns value
The code:
graph::graph(const char *file_name) {
ifstream infile(file_name);
istringstream iss;
int R = 2; // number of rows
int C = 4; // number of columns
for (int i=0; i<R*C; i++) add_vertex(i+1);
adj = new std::vector<edge*>[R*C]; // adjacency list
// add all edges to the grid
for (int r=0; r<R; r++) {
for (int c=0; c<C; c++) {
if (c!=C-1) add_edge(vertices[r*C+c], vertices[r*C+(c+1)]);
if (r!=R-1) add_edge(vertices[r*C+c], vertices[(r+1)*C+c]);
}
}
int P = 2; // number of vertices holding a special value
for (int i=0; i<P; i++) {
getline(infile, line);
iss.str(line);
iss >> r >> c >> p;
vertices[r*C+c]->set_value(p);
p_vertices.push_back(vertices[r*C+c]);
iss.clear();
}
void graph::add_vertex(int v) {
auto *vert = new vertex(v);
vertices.push_back(vert);
}
void graph::add_edge(vertex *v, vertex *u) {
edge e = std::make_tuple(v, u, 1);
adj[v->get_id()].push_back(&e);
adj[u->get_id()].push_back(&e);
}
Header:
#include "vertex.h"
typedef std::tuple<vertex*, vertex*, int> edge;
class graph {
private:
std::vector<vertex*> vertices; // all vertices
std::vector<vertex*> p_vertices; // vertices with a special value
std::vector<edge*> *adj; // adjacency list
public:
explicit graph(const char *file_name);
void add_vertex(int v);
void add_edge(vertex *v, vertex *u);
};
Header for a vertex:
#include <string>
#include <vector>
class vertex {
private:
int id;
int val;
public:
explicit vertex(int id) {
this->id = id;
this->val = 0;
};
int get_id() { return id; };
void set_value(int p) { val = p; };
};
Example input:
0 0 1
1 2 3
The error disappears if I comment out this line:
p_vertices.push_back(vertices[r*C+c]);
And remains even if I try to change p_vertices to std::vector<int> instead of std::vector<vertex*> (and use p_vertices.push_back(r*C+c)).
Thanks for any hints on how to fix the error.

Related

"malloc(): corrupted top size" when constructing vector

I'm trying to create this function:
std::vector<int> graph::getNeighbors(int n){
int i = 0; for(int el : verteces[n]) i++;
if( i != 0){
auto iter = verteces[n].begin();
std::vector<int> res = std::vector<int>{i};
for(int j=0; j<i; j++)
res[j] = *(iter++);
return res;
}
return std::vector<int>{};
}
As the name itself explain, it is supposed to get the neighbors of a vertex. The graph is made like this:
class graph {
private:
std::vector<std::forward_list<int>> verteces;
unsigned long int n;
ยทยทยท
};
Now, the problem is that whenever i is greater than 0, the program crashes badly with the error:
malloc(): corrupted top size
I don't understand what I am doing wrong.
EDIT
In order to make a reproducible example I am going to show all the three files.
main.cpp:
#include <iostream>
#include <set>
#include "graph/graph.h"
void greedyAlgorithm(graph &G){
std::vector<int> colors{static_cast<int>(G.getSize())};
for(int i=0; i<G.getSize(); i++)
colors[i] = -1;
for(int i=0; i<G.getSize(); i++){ // for each vertex
std::set<int> colorNeigh{};
for(auto &j : G.getNeighbors(i)){
if(colors[j] != -1)
colorNeigh.insert( colors[j] );
}
int col = 0;
for(auto &el : colorNeigh){
if(el == col) col++;
else break;
}
colors[i] = col;
}
}
int main() {
{
std::vector<int> r;
for(int i=0; i<100; i++)
r.push_back(i);
}
graph a = graph(10);
a.addEdge(2, 5);
a.addEdge(2, 5);
a.addEdge(1,2);
a.addEdge(2,3);
a.addEdge(3,4);
greedyAlgorithm(a);
return 0;
}
graph.h:
//
// Created by salvo on 11/08/21.
//
#ifndef P2_GRAPH_H
#define P2_GRAPH_H
#include <forward_list>
#include <vector>
#include <stdexcept>
class node;
// list implementation
class graph {
private:
std::vector<std::forward_list<int>> verteces;
unsigned long int n;
public:
graph();
graph(unsigned long int n); // vertex number
void addEdge(int a, int b);
std::vector<int> getNeighbors(int n);
unsigned long getSize(){return n;};
};
#endif //P2_GRAPH_H
graph.cpp:
//
// Created by salvo on 11/08/21.
//
#include <iostream>
#include <openssl/ossl_typ.h>
#include "graph.h"
graph::graph() {
// verteces call default constructor
n = 0;
}
graph::graph(unsigned long int n) {
verteces = std::vector<std::forward_list<int>>{n};
for(auto &el : verteces) el = std::forward_list<int>{};
this->n = n;
}
void graph::addEdge(int a, int b) {
if(a == b){
std::cout << " No self loop!\nexiting ";
exit(-2);
}
int m = a > b ? a : b + 1;
if(m > n){
std::cout << "The graph only contains " << n << " verteces.\n exiting.";
exit(-1);
}
// Check if the edge exist already
for(auto &el : verteces[a]){
if(el == b) return;
}
verteces[a].emplace_front(b);
verteces[b].emplace_front(a);
std::cout << verteces.size() << std::endl;
}
std::vector<int> graph::getNeighbors(int n){
std::vector<int> res{};
for(auto el : verteces[n])
res.push_back(el);
return res;
}
Output if executed:
malloc(): corrupted top size
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
I am using C++14.
Without even looking at the code, I added -D_GLIBCXX_DEBUG1 to compiler flags (to enable container bounds checks) and got this:
Error: attempt to subscript container with out-of-bounds index 1, but
container only holds 1 elements.
Then I used GDB to understand where exactly that happens:
void greedyAlgorithm(graph &G){
std::vector<int> colors{static_cast<int>(G.getSize())};
for(int i=0; i<G.getSize(); i++)
colors[i] = -1; <-- HERE
This means that the syntax you used created a vector with a single element (with value G.getSize()).
This is why you should never EVER use direct-list-initialization (i.e. with curly braces, without =) with containers. If the vector had some other element type (not a number), this would've worked, and this is exactly why you shouldn't do it.
The fix is to use parentheses:
std::vector<int> colors(static_cast<int>(G.getSize()));
1 This is libstdc++-specific flag (it only works with the GCC's standard library). Other standard library implementations have similar checks. There are also address sanitizers that could also work here.
std::vector<int> colors{static_cast<int>(G.getSize())}
Constructs a vector with one element equal to static_cast<int>(G.getSize()). You want std::vector colors(here_the_size) not with { }. std::vector colors(G.getSize()); will construct a vector with G.getSize() elements.
Because subsequent colors[i] = -1; overwrites memory without any checks, you get errors.
Use .at() instead of []. Using colors.at(i) = -1; will allow you to detect errors early on.

How to return structure array in C++

So I've been trying to implement Kruskal's algorithm, first I want to make clear the question is not related to the implementation of the algorithm. I've created one graph.hpp file, one kruskalsAlgo.hpp and main.cpp as follows respectively:
#pragma once
struct Edge
{
int source;
int destination;
int weight;
};
struct Graph
{
int V;
int E;
Edge* edge;
};
Graph* create_graph(int V, int E)
{
Graph* graph = new Graph;
graph -> V = V;
graph -> E = E;
graph -> edge = new Edge[E];
return graph;
}
#include <stdlib.h>
#include <tuple>
#include "../Graph/Graph.hpp"
class Kruskals_Algo
{
private:
struct subset
{
int parent;
int rank;
};
void make_set(subset*, int);
int find_set(subset*, int);
void _union(subset*, int, int);
public:
Edge* kruskal(Graph*);
void print_kruskals_MST(Edge*, int);
};
void Kruskals_Algo::make_set(subset* subsets, int V)
{
subsets[V].parent = V;
subsets[V].rank = 0;
}
int Kruskals_Algo::find_set(subset* subsets, int V)
{
if(subsets[V].parent != V)
subsets[V].parent = find_set(subsets, subsets[V].parent);
return subsets[V].parent;
}
void Kruskals_Algo::_union(subset* subsets, int x, int y)
{
int xroot = find_set(subsets, x);
int yroot = find_set(subsets, y);
if(subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if(subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
inline int myComp(const void* a, const void* b)
{
Edge* a1 = (Edge*)a;
Edge* b1 = (Edge*)b;
return a1 -> weight > b1 -> weight;
}
Edge* Kruskals_Algo::kruskal(Graph* graph)
{
int V = graph -> V;
Edge result[V];
Edge* result_ptr = result;
int e = 0;
int i = 0;
qsort(graph -> edge, graph -> E, sizeof(graph -> edge[0]), myComp);
subset* subsets = new subset[(V * sizeof(subset))];
for (int v = 0; v < V; ++v)
make_set(subsets, v);
while(e < V - 1 && i < graph -> E)
{
Edge next_edge = graph -> edge[i++];
int x = find_set(subsets, next_edge.source);
int y = find_set(subsets, next_edge.destination);
if (x != y)
{
result[e++] = next_edge;
_union(subsets, x, y);
}
}
//return std::make_tuple(res, e);
return result_ptr;
}
void Kruskals_Algo::print_kruskals_MST(Edge* r, int e)
{
int minimumCost = 0;
for(int i=0; i<e; ++i)
{
std::cout << r[i].source << " -- "
<< r[i].destination << " == "
<< r[i].weight << std::endl;
minimumCost = minimumCost + r[i].weight;
}
std::cout << "Minimum Cost Spanning Tree: " << minimumCost << std::endl;
}
#include <iostream>
#include "Graph/Graph.hpp"
#include "Kruskals_Algo/kruskalsAlgo.hpp"
//#include "Prims_Algo/primsAlgo.hpp"
using namespace std;
class GreedyAlgos
{
public:
void kruskals_mst();
//void prims_mst();
};
void GreedyAlgos::kruskals_mst()
{
Kruskals_Algo kr;
int V;
int E;
int source, destination, weight;
cout << "\nEnter the number of vertices: ";
cin >> V;
cout << "\nEnter the number of edges: ";
cin >> E;
Edge* res;
Graph* graph = create_graph(V, E);
for(int i=0; i<E; i++)
{
cout << "\nEnter source, destinstion and weight: ";
cin >> source >> destination >> weight;
graph -> edge[i].source = source;
graph -> edge[i].destination = destination;
graph -> edge[i].weight = weight;
}
//std::tie(result, E) = kr.kruskal(graph);
res = kr.kruskal(graph);
kr.print_kruskals_MST(res, E);
}
int main()
{
int choice;
GreedyAlgos greedy;
greedy.kruskals_mst();
return 0;
}
So my question here is when I debug the program the values in Edge result[V], which is a structure array, are calculated correctly, at position [0] [1] [2] as in the following picture:
but when the function print_kruskals_MST(res, E) is called from the main the values printed are different:
Is there any pointer thing that I'm doing wrong?
Thanks in advance!
P.S. Ignore the comments!
This answer might not answer your question directly but it should shed some light on the problem.
First of all, yes you have a lot of pointer problems...
Secondly, pair ANY use of the new operator with the delete operator. As it stands, you have a bunch of memory leaks.
Also, why create_graph? Create a constructor for Graph instead (and a destructor since the class has an Edge* edge it needs to take care of).
struct Graph
{
int V;
int E;
Edge* edge;
// constructor
Graph(int V, int E)
{
this->V = V;
this->E = E;
this->edge = new Edge[E];
}
// destructor
~Graph()
{
// nullify the member variable before deleting its memory is just a safety measure pertaining to multithreading.
Edge* _edge = this->edge;
this->edge = nullptr;
delete _edge;
}
};
Then change Graph* graph = create_graph(V, E); into Graph* graph = new Graph(V, E); and do delete graph when you're done using it.
Make sure you remove all memory leaks and we can go on to discussing referencing the correct data (f.ex. by me changing my answer).

Passing an integer pointer to a constructor and getting runtime memory error

I'm trying to create a vector of a class-name vertex. The value of "n" is not known at compile-time so I'll be using new to create to create the "path" array. But the problem occurs when I create the input array in a function and push it in the vector.
int n;
class vertex {
public:
int *path;
int visited = 0;
vertex(int *y) {
path = new int(n);
for (int i = 0; i < n; i++)
path[i] = y[i];
}
};
void inp(vector<vertex> graph) {
int t1[] = { 0,1,0,0 };
int t2[] = { 0,0,1,0 };
int t3[] = { 0,0,0,1 };
int t4[] = { 0,0,0,0 };
graph.push_back(vertex(t1));
graph.push_back(vertex(t2));
graph.push_back(vertex(t3));
graph.push_back(vertex(t4));
}
int main() {
n=4;
vector<vertex> graph;
inp(graph);
_getch();
}
For simplicity I've created t1 to t4 as static arrays. But still it shows some error at runtime
1:try use: path = new int [n], rather than path = new int(n);
2:if you want to push elements to graph, you should change your function inp to void inp(vector<vertex>& graph)

Typedef array referencing?

Hello I have a question regarding the usage of typedef in C++. I am trying to create my own graph class where I can perform DFS and BFS. I have attached what I have for the class so far. But every time I try to compile I run into certain errors that I just do not know how to fix. I am sure the error has something to do with the variable vertexList that I use to hold all the vertices.
#include <iostream>
#include <stack>
class myGraph{
public:
typedef struct Vertex{
char label;
bool visited;
}Vertex;
myGraph(int);
void AddVertex(char);
void addEdge(int, int);
int adjUnvisited(int);
void displayVertex(int);
void dfs();
private:
Vertex* vertexList;
int** adjMatrix;
int size;
int vertices;
int count;
};
myGraph::myGraph(int size){
count = 0;
size = size;
vertices = size;
vertexList = new Vertex[vertices];
adjMatrix = new int*[size];
for(int i=0; i<size; i++){
adjMatrix[i] = new int[vertices];
}
for(int i=0; i<vertices; i++){
for(int j=0; j<vertices; j++){
adjMatrix[i][j] = 0;
}
}
}
void myGraph::AddVertex(char label){
Vertex* myVertex = new Vertex();
myVertex->label = label;
myVertex->visited = false;
vertexList[count++] = myVertex;
}
void myGraph::addEdge(int a, int b){
adjMatrix[a][b] = 1;
adjMatrix[b][a] = 1;
}
int myGraph::adjUnvisited(int index){
for(int i=0; i<vertices; i++){
if(adjMatrix[i][index]==1 && vertexList[i]->visited==false){
return i;
}
}
return -1;
}
void myGraph::displayVertex(int index){
std::cout << "Current vertex: " << vertexList[index]->label << std::endl;
}
void myGraph::dfs(){
std::stack<int> myStack;
int temp = 0;
vertexList[temp]->visited = true;
myStack.push(temp);
int unvisitedVertex;
while(!myStack.empty()){
unvisitedVertex = adjUnvisited[myStack.top()];
if(unvisitedVertex!=-1){
myStack.push(unvisitedVertex);
displayVertex(unvisitedVertex);
vertexList[unvisitedVertex]->visited = true;
}else{
myStack.pop();
}
}
}
The error message that I get is this:
no viable overloaded '=' vertexList[count++] = myVertex;
Along with a note:
candidate function (the implicit copy assignment
operator) not viable: no known conversion from 'struct Vertex *' to
'const myGraph::Vertex' for 1st argument; dereference the argument with *
struct Vertex{
And some other error messages which are (I'm sure these are very minor and I can figure them out):
member reference type 'struct Vertex' is not a
pointer; maybe you meant to use '.'?
if(adjMatrix[i][index]==1 && vertexList[i]->visited==false){
reference to non-static member function must be called
unvisitedVertex = adjUnvisited[myStack.top()];
Now I am not sure what exactly I am doing wrong and was wondering if someone here could help me out.
Thank you very much for all your help!
You've declared vertexList as a pointer-to-Vertex - which is fair enough, since it's going to be an array. But that means that each element of that array is a Vertex structure - yet you're accessing each array element as though it was a pointer.
Either:
Replace all the ->s with .s and do something different in AddVertex()
Declare vertexList as a Vertex ** (like adjMatrix)

expected type specifier before vector

I have seen previous questions related to this error but I got nothing that solved my problem. I have commented lines which could have created this same error. Heres the code Im using
In file path.h
#ifndef PATH_H
#define PATH_H //same PATH_H for ifndef and define
#include <vector>
class face{
std::vector<unsigned int>face_index; //std namespace is used for vector
std::vector<vector3d>face_vertex; //to avoid conflict
std::vector<vector3d>midpoint; //vector3d is a class
public:
face(std::vector<unsigned int>*fid, std::vector<vector3d>*fv, std::vector<vector3d>*mid)
{
face_index = *fid; //to assign values
face_vertex = *fv;
midpoint = *mid;
}
};
class path{
std::vector<face*>faces; //pointer used
std::vector<vector3d> path_verts;
public:
publicfunc();
~path(); //destructor used
};
#endif
In file path.cpp,
#include "path.h" //header file used
void path::publicfunc()
{
std::vector<unsigned int>face_i; //for face_index
std::vector<vector3d>face_v; //for face_vertices
std::vector<vector3d>midp; //for midpoint
unsigned int f_index[3];
vector3d f_vertex[3];
for(unsigned int i = 0; i < meshV->mNumVertices; i++)
{
const aiVector3D* pPos = &(meshV->mVertices[i]);
path_verts.push_back(vector3d(pPos->x, pPos->y, pPos->z));
}
//path_verts has stored vertices now
for(unsigned int i=0; i<meshV->mNumFaces; i++)
{
face_i.push_back(i); //push back unsigned int
vector3d mid;
aiFace face=meshV->mFaces[i];
for(int j=0;j<face.mNumIndices;j++) //0..2
{
f_index[j] = face.mIndices[j];
f_vertex[j] = path_verts[f_index[j]]; //get verts using indices
face_v.push_back(f_vertex[j]); //push back vector3d
}
mid/=3; //median of triangle
midp.push_back(mid); //push back median
faces.push_back(new face(&face_i, &face_v, &midp)); //error line
}
}
path::~path()
{
for(int i = 0; i<faces.size(); i++)
{
delete faces[i]; //free memory
}
}
The error shown is expected type specifier before face.
The face that it`s talking about is the one after 'new'.