c++ segmentation fault trying to access vector - c++

Im trying to create a adjacency representation of a graph.
I wrote a small program using vectors of vectors , however I keep getting "segmentation fault" but the compiler(clang++ version 5.0.1 on Windows) it seems wereever I try to access the vector vertex_matrix its giving a segmentation fault, why is it not being instantiated?
Here is the header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
Here is the cpp implementation:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix[i]=(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
cout << "vertex_matrix size:" << vertex_matrix.size() << endl;
for (int i=0; i< num_of_vertices; i++)
{
for (int j = 0; j < num_of_vertices; j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
Here is the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
I edited the above code to use pass by reference, however the matrix still prints as 0's.
Please help with pass by reference, updates below:
Header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & matrix);
void print_graph();
std::vector<std::vector<int>> vertex_matrix;
private:
int num_of_vertices;
int num_of_edges;
};
#endif
Cpp file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices) {
if (num_of_vertices == 0) {
num_of_vertices = 10;
}
for (int i = 0; i < num_of_vertices; i++) {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.push_back(vector<int> (num_of_vertices, INT_MAX));
}
}
graph::~graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & _matrix) {
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = _matrix[v1 - 1];
if (columnVector[v2 - 1] == INT_MAX) {
columnVector[v2 - 1] = weight;
}
}
void graph::print_graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix.size(); j++) {
//vertex_matrix[i][j]
std::vector<int> columnVector = matrix[i];
if (columnVector[j] != INT_MAX) {
std::cout << columnVector[j];
} else {
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
main:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
std::vector<std::vector<int>>& m = _graph.vertex_matrix;
_graph.add_edge(1,2,1,m);
_graph.add_edge(2,3,1,m);
_graph.add_edge(3,1,1,m);
_graph.add_edge(3,3,1,m);
_graph.add_edge(3,4,1,m);
_graph.add_edge(4,0,0,m);
_graph.print_graph();
}
Any help will be appreciated.
Thanks

You create an empty vector and then try to access elements in it. Change your constructor to
graph::graph(size_t _num_of_vertices) :
vertex_matrix(
std::vector<std::vector<int>>(
_num_of_vertices,std::vector<int>(_num_of_vertices)
)
)
{}
to create a correctly sized vector.
Also in case _num_vertices == 0 you set it to 10 but thats after you initialized the member num_vertices so you leave the object in an inconsistent state. There are different ways to fix that, I would probably just throw an exception when the number of vertices passed is zero, or just ignore it. User wants a zero sized matrix? Why not?
Moreover the size should be unsigned not signed, there is size_t for container sizes. Even better you shouldnt have that member at all, because a vector already knows its size, the only reason to repeat that information is to introduce mistakes ;)

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.

Cout from class method does nothing

I have a class "beaker" that represents a beaker with n-dices that have n-faces. It has a method "roll" which returns a vector with n-elements where each element represents a dice. Then I have another class "board" that for now, it only prints the values generated by beaker.roll using cout;
So I call the beaker.roll function to pass the result to print them, but it does nothing. I have no compile errors/IntelliSense warnings. What am I doing wrong?
#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <vector>
using std::cout;
using std::vector;
class beaker {
public:
int diceCount, diceFaces;
beaker() {
diceCount = 2;
diceFaces = 6;
};
beaker(int count, int faces) {
diceCount = count;
diceFaces = faces;
};
//Dice values
vector<uint8_t> dice;
//METHODS
//RETURN DICE i VALUE
int diceValue(int d) {
return dice.at(d-1);
}
//ROLL DICE + RETURN RESULT
vector<uint8_t> roll() {
std::mt19937 mt(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> dist(1, diceFaces);
for (int i=0; i<diceCount; i++) {
dice.push_back(dist(mt));
}
return dice;
}
//RETURN LAST DICE NUMBERS
vector<uint8_t> result() {
return dice;
}
};
class board {
public:
void Print(vector<uint8_t> dice) {
for (int i=0; i<dice.size(); i++) {
cout << dice.at(i);
}
}
};
int main() {
beaker beaker;
board board;
board.Print(beaker.roll());
}
The problem is that the values in dice are of type uint8_t, which the cout::<< operator is interpreting as unsigned char, so it is printing out the values as ASCII characters. However, the values are between 1 and 6, and ASCII characters less than 32 are mostly non-printing characters, so they aren't visible in the output.
To convince the cout::<< operator to print the values as integers instead, update the code to this:
void Print(vector<uint8_t> dice) {
for (int i=0; i<dice.size(); i++) {
cout << static_cast<int>(dice.at(i));
}
cout << std::endl; // just to make sure the buffer gets flushed ASAP
}

c++ vector's member are not updating

Im trying to write a adjacency matrix representation using vectors of integer vectors , therefore vector> . However when I add members to the vector and later try and print those values nothing has changed. Most likely it has to do with "pass by value" however I have used "pass by reference" to the best of my knowledge.
Here is my header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
the cpp implementation file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix.push_back(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
for (int i=0; i< vertex_matrix.size(); i++)
{
for (int j = 0; j < vertex_matrix.size(); j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
When I use the print function I currently getting 0's.
How can I make this proper pass by reference, and have the updated values print.
Thanks
As stated in the comments, you are creating a copy of your column and then modifying the copy. What you want to do is to make a reference to it.
vector<int>& columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
Or you can access the element directly.
if (vertex_matrix[v1-1][v2-1] == INT_MAX)
{
vertex_matrix[v1-1][v2-1] = weight;
}
In print_graph you are doing the same, but here you are not modifying anything so that works, but you are making an unnecessary copy for no reason which is not ideal.
A last point is that you are calling vertex_matrix.clear() in your destructor. This is redundant, when the vector goes out of scope it will clear itself up, so you don't need to manage that.

C++ Vectors in a Class

i am working on a worksheet i have for university and the question asks me to "Allow a user to enter 10 numbers from the keyboard into an array" however we have been told that we need to use classes and vectors for this task. When i run my code i get an error stating: "Expression: Vector subscript out of range"
can anyone help?
Array.h
#include <iostream>
#include <vector>
using namespace std;
class Array
{
private:
vector<int> lists;
public:
void fillArray();
void printForwards();
void halfandHalf();
void shiftArrayRight();
Array();
Array(vector<int>);
};
Array.cpp
#include "Array.h"
Array::Array()
{
lists[10];
}
Array::Array(vector<int> lists)
{
this->lists = lists;
}
void Array::fillArray()
{
for (int i = 0; i < 10; i++)
{
cin >> lists[i];
}
}
void Array::printForwards()
{
for (int i = 0; i < 10; i++)
{
cout << lists[i];
}
}
Source.cpp
#include <iostream>
#include "Array.h"
using namespace std;
int main()
{
Array list1,list2;
//fill array 1
list1.fillArray();
//fill array 2
list2.fillArray();
// print array 1
list1.printForwards();
//print array 2
list2.printForwards();
system("pause");
return 0;
}
Thanks in advance
lists[10]; is not going to create a vector of size 10. It is going to try and access the 11th element of an empty vector. If you wanted to create a vector of size 10 then you can use
Array::Array() : lists(std::vector<int>(10, 0)) {}
I would also suggest you change
Array::Array(vector<int> lists)
{
this->lists = lists;
}
To
Array::Array(vector<int> lists) lists(lists) {}
You should also change your for loops to use the vector size() instead of a hard coded value
void Array::fillArray()
{
for (int i = 0; i < lists.size(); i++) // uses size()
{
cin >> lists[i];
}
}
void Array::printForwards()
{
for (int i = 0; i < lists.size(); i++) // uses size()
{
cout << lists[i];
}
}
Or if you have C++11 or higher you can use a ranged based for loop like
void Array::fillArray()
{
for (auto& e : lists)
{
cin >> e;
}
}
void Array::printForwards()
{
for (const auto& e : lists)
{
cout << e;
}
}

get value from another class c++

Hello I have a getter in adjacencyMatrix class
int AdjacencyMatrix::getVertexFirst() const { return vertexFirst; }
and constructor
AdjacencyMatrix::AdjacencyMatrix() {
this->vertexCount=0;
this->vertexFirst=0;
this->edgeCount=0;
this->matrix=0;
this->wage=0;
}
bool AdjacencyMatrix::createFromFile(string path) {
fstream file;
file.open(path.c_str(), fstream::in);
if (file.good())
{
int vertexF,vertexE,wag;
file >> this->edgeCount;
file >> this->vertexCount;
file >> this->vertexFirst;
matrix = new int *[vertexCount];
wage = new int *[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
matrix[i]=new int[vertexCount];
wage[i]=new int[vertexCount];
}
//fill matrix by zeros
for (int i = 0; i < vertexCount; i++)
{
for(int j=0; j<vertexCount;j++)
{
matrix[i][j]=0;
wage[i][j]=0;
}
}
// fill matrix by 1
for(int i=0; i<edgeCount; i++)
{
file >> vertexF >> vertexE >> wag;
this->matrix[vertexF][vertexE]=1;
this->wage[vertexF][vertexE]=wag;
}
file.close();
return true;
}
return false;
}
of course print works in Adjacency class
And now I want to have this value in Dijkstra class
//Dijkstra.cpp
#include "Dijkstra.h"
AdjacencyMatrix am;
bool Dijkstra::makeDijkstraAlgo() {
int vertexCount=am.getVertexCount();
int vertexFirst=am.getVertexFirst();
int **wage=am.getWage();
cout << vertexCount;
cout << vertexFirst;
.......... }
this is my main class
#include <iostream>
#include "Dijkstra.h"
#include "Screen.h"
using namespace std;
int main() {
AdjacencyMatrix am;
Dijkstra dijkstra;
am.createFromFile("matrix.txt");
dijkstra.makeDijkstraAlgo();
dijkstra.viewDijkstra();
return 0;
}
and this cout show only 0, but in AdjacencyMatrix show normal value. Can you help me ?
UPDATE
I notice that always will be 0 because I initialized value in constructor....
So How to make something like this
I create a matrix from file and add value to vertexCount etc.
am.createFromFile("matrix.txt");
now I want to get this value(vertexCount etc.) from adjacency matrix class to Dijkstry class and make
dijkstra.makeDijkstraAlgo();
dijkstra.viewDijkstra();
How can I solve it ?
You're creating one matrix but using another.
makeDijkstraAlgo uses the global matrix called ”am”, but main has its own matrix by the same name.
Get rid of the global and pass main's matrix to the function
bool Dijkstra::makeDijkstraAlgo(const AdjacencyMatrix& am) {
int vertexCount=am.getVertexCount();
int vertexFirst=am.getVertexFirst();
int **wage=am.getWage();
cout << vertexCount;
cout << vertexFirst;
// ...
}
int main() {
AdjacencyMatrix am;
Dijkstra dijkstra;
am.createFromFile("matrix.txt");
dijkstra.makeDijkstraAlgo(am);
dijkstra.viewDijkstra();
return 0;
}