How to copy a vector of lists? - c++

In my program I need to copy (or even use) a private data structure into the .cpp file of a completely different class. At the moment I am even having trouble just simply accessing it remotely, it seg faults when I try to print it. Here is a simplified version of my class with the data structure:
class Graph
{
private:
class Edge
{
public:
Edge(string vertex, int weight)
{
m_vertex = vertex;
m_weight = weight;
}
~Edge(){}
string m_vertex;
int m_weight;
};
vector< list<Edge> > adjList;
public:
Graph();
~Graph();
vector < list < Edge > > get_adjList(){return adjList;}
//Other functions....
};
In a completely different function I try to do this...
void MinPriority::testPrint(string targetVertex) //FOR TESTING PURPOSES SO FAR (FAILS TO WORK) SEGMENTATION FAULT NO MATTER WHAT
{
targetVertex = "A";
Graph graph;
graph.adjList = graph.get_adjList(); //adjList is our empty container based on the array of linked lists
/*1*/cout << graph.get_adjList()[0].front().m_vertex << " TEST!" << endl;
/*2*/cout << "The very first vertex is: ";
if(graph.adjList.size() == 0)
cout << "NULL<!>" << endl;
else cout << graph.adjList[0].front().m_vertex << endl;
}
Note i set targetVertex to 'a' so my program compiles since im including -Werror in my makefile (required for assignment).When I comment out /*1*/ and run down to /*2*/ the output will always be "The very first vertex is: NULL<!>", no matter how many elements are in the data structure. At /*1*/ I try to print out the object returned by the function get_adjList() but it seg faults reading this:
Exception: STATUS_ACCESS_VIOLATION at eip=611298C5
eax=0A0A0A0A ebx=01010101 ecx=20050884 edx=F5F5F5F5 esi=20058488 edi=20060000
ebp=0028A8D8 esp=0028A8D0 program=C:\cygwin\home\Ryan\311\P5Dec16\Graph.exe, pid 5612, thread main
cs=0023 ds=002B es=002B fs=0053 gs=002B ss=002B
Stack trace:
Frame Function Args
0028A8D8 611298C5 (20058400, 0000000A, 20058488, 610FD3CA)
0028A938 6115F91F (0028D41C, 61187720, 0028A958, 0043455D)
0028A988 61137BF7 (0028D41C, 20058400, 00000001, 20058488)
0028A9B8 61137CD5 (20058400, 00000001, 20058488, 61187720)
0028A9D8 610D6745 (00449240, 20058400, 20058488, 004493C4)
0028AA68 004439BA (004493C0, 6123D5FC, 004452B4, 0028AAA0)
0028AB08 00402756 (0028AC20, 0028ABB0, 20010100, 004011C1)
0028AC68 00401583 (00000001, 0028AC90, 20010100, 612757A2)
0028ACF8 6100763A (00000000, 0028CD78, 61006C50, 00000000)
End of stack trace
Segmentation fault (core dumped)
Basically in short, I would like to know what this stack trace is (I have had seg faults before but I have never seen this). I would like to know how to properly access the data structure from class Graph in other files that #include "Graph.h". I am also unsure how to copy my object inside of testPrint();. Why is it that this works perfectly in Graph.cpp?
void Graph::set_array(string vertex)
{
//increment vector size by 1 and insert a new Edge object into the vector of linked lists
cout << "ADDING " << vertex << " TO VECTOR" << endl;
adjList.resize(adjList.size() + 1);
adjList[adjList.size() - 1].push_back(Edge(vertex, 0));
}

Graph graph;
As you stated, the default constructor of Graph does nothing. So at this point, graph.adjList is empty.
graph.adjList = graph.get_adjList();
This is a pointless statement which assigns to graph.adjList from a copy of itself. Since it was empty before, it is still empty now.
cout << graph.get_adjList()[0].front().m_vertex << " TEST!" << endl;
This tries to access the first element of (a copy of) graph.adjList. But graph.adjList is empty (i.e. it doesn't have a first element), so this is undefined behavior. It may or may not be the cause of your segfault, but it is certainly a problem that must be fixed before any further useful debugging can take place.

Related

Why iterator is not dereferenced as an lvalue

Apologies if my question does not contain all relevant info. Please comment and I will amend accordingly.
I use CLion on Win7 with MinGW and gcc
I have been experimenting with circular buffers and came across boost::circular_buffer, but for the size of my project I want to use circular buffer by Pete Goodlife, which seems like a solid implementation in just one .hpp.
Note: I am aware of how to reduce boost dependecies thanks to Boost dependencies and bcp.
However, the following example with Pete's implementation does not behave as expected, i.e. the result to std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin()); comes out empty. I would like to understand why and possibly correct its behaviour.
Follows a MWE:
#include "circular.h"
#include <iostream>
#include <algorithm>
typedef circular_buffer<int> cbuf_type;
void print_cbuf_contents(cbuf_type &cbuf){
std::cout << "Printing cbuf size("
<<cbuf.size()<<"/"<<cbuf.capacity()<<") contents...\n";
for (size_t n = 0; n < cbuf.size(); ++n)
std::cout << " " << n << ": " << cbuf[n] << "\n";
if (!cbuf.empty()) {
std::cout << " front()=" << cbuf.front()
<< ", back()=" << cbuf.back() << "\n";
} else {
std::cout << " empty\n";
}
}
int main()
{
cbuf_type cbuf(5);
for (int n = 0; n < 3; ++n) cbuf.push_back(n);
print_cbuf_contents(cbuf);
cbuf_type df(5);
std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin());
print_cbuf_contents(df);
}
Which prints the following:
Printing cbuf size(3/5) contents...
0: 0
1: 1
2: 2
front()=0, back()=2
Printing cbuf size(0/5) contents...
empty
Unfortunately, being new to c++ I can’t figure out why the df.begin() iterator is not dereferenced as an lvalue.
I supsect the culprit is (or don't completely uderstand) the member call of the circular_buffer_iterator on line 72 in Pete's circular.h:
elem_type &operator*() { return (*buf_)[pos_]; }
Any help is very much appreciated.
The iterator you pass as the output iterator is dereferenced and treated as an lvalue, and most probably the data you expect is actually stored in the circular buffer's buffer.
The problem is, that apart from the actual storage buffer, most containers also contain some internal book-keeping state that has to be maintained. (for instance: how many elements is in the buffer, how much frees space is left etc).
Dereferencing and incrementing the container doesn't update the internal state, so the container does not "know" that new data has been added.
Consider the following code:
std::vector<int> v;
v.reserve(3);
auto i = v.begin();
*(i++) = 1; // this simply writes to memory
*(i++) = 2; // but doesn't update the internal
*(i++) = 3; // state of the vector
assert(v.size() == 0); // so the vector still "thinks" it's empty
Using push_back would work as expected:
std::vector<int> v;
v.reserve(3);
v.push_back(1); // adds to the storage AND updates internal state
v.push_back(2);
v.push_back(3);
assert(v.size() == 3); // so the vector "knows" it has 3 elements
In your case, you should use std::back_inserter, an iterator that calls "push_back" on a container every time it is dereferenced:
std::adjacent_difference(
cbuf.begin(), cbuf.end(),
std::back_inserter(df));
std::adjacent_difference writes to the result iterator. In your case, that result iterator points into df, which has a size of 0 and a capacity of 5. Those writes will be into the reserved memory of df, but will not change the size of the container, so size will still be 0, and the first 3 ints of the reserved container space will have your difference. In order to see the results, the container being written into must already have data stored in the slots being written to.
So to see the results you must put data into the circular buffer before the difference, then resize the container to the appropriate size (based in the iterator returned by adjacent_difference.

C++: vector size is wrong and higher than the number of elements

In my attempt to load .OBJ-files I load vertex data into std::vectors to send them to the GPU later. I fill three vectors, for normals, vertices and texture coordinates. The size of the normal vector is far higher than the size of the other two vectors, even if its filled with the same number of elements.
Code:
SceneTree* generateSceneTree(OBJScene* scene){
PostProcessing::triangulateFaces(scene);
SceneNode* node = new SceneNode;
vector<Vec<3>>& sceneNormals = scene->attributeData[Attribute::Normal];
vector<Vec<3>>& sceneVertices = scene->attributeData[Attribute::Position];
vector<Vec<3>>& sceneTexCoords = scene->attributeData[Attribute::TexCoord];
map<string,MaterialInfo*> mtls;
for(string s : scene->mtlLibs){
auto temp = loadMTL(s);
mtls.insert(temp.begin(),temp.end());
}
vector<Vec<3>> meshNormals; <-- creating vectors here.
vector<Vec<3>> meshVertices;
vector<Vec<2>> meshTexCoords;
for(auto g : scene->groups){
meshNormals.clear();
meshNormals.reserve(g.faces.size()*3);
meshVertices.clear();
meshVertices.reserve(g.faces.size()*3);
meshTexCoords.clear();
meshTexCoords.reserve(g.faces.size()*3);
AABB bBox;
cout << "num of faces: " << g.faces.size() << endl;
for(auto f : g.faces){
for(auto p : f.points){
uint vIndex = p.indices[Attribute::Position];
uint nIndex = p.indices[Attribute::Normal];
uint tIndex = p.indices[Attribute::TexCoord];
Vec<3> n = sceneNormals.at(nIndex);
Vec<3> v = sceneVertices.at(vIndex);
Vec<3> t = sceneTexCoords.at(tIndex);
meshNormals.push_back(n);
meshVertices.push_back(v);
meshTexCoords.push_back(t.toVec<2>());
bBox += meshVertices.back();
}
}
cout << "meshNormals size: " << meshNormals.size() << endl;
cout << "meshVertices size: " << meshVertices.size() << endl;
cout << "meshTexCoords size: " << meshTexCoords.size() << endl;
Mesh* m = new Mesh({
{meshVertices,Attribute::Position},
{meshNormals,Attribute::Normal},
{meshTexCoords,Attribute::TexCoord}
},GL_TRIANGLES);
SceneLeaf* leaf = new SceneLeaf;
leaf->nodeData = {Matrix4(),bBox};
leaf->leafData = {m, mtls[g.mtlName]};
node->addChild(leaf);
}
return node;
}
Output:
num of faces: 1087474
meshNormals size: 2958875950
meshVertices size: 3262422
meshTexCoords size: 3262422
This seems highly illogical. The program crashs afterwards with a std::bad_array_new_length exception because the Mesh class cant create an array of size 2958875950 to send to the GPU.
Update:
If I swap the declarations of meshVertices and meshNormals, meshVertices has the wrong size. So the first created vector is affected.
If I use std::list instead of std::vector, everything works.
If I comment out the ....reserve(g.faces.size()*3); lines, a std::bad_alloc is thrown.
My guess is that you have a memory corruption bug "somewhere" that is overwriting the meshNormals variable on the stack. The fact that swapping the meshNormals and meshVertices declarations leads to meshVertices becoming bad matches that theory.
To narrow in on the problem you can do a few things:
Comment out all lines in the inner for(auto p : f.points) loop and see if the error still occurs.
Assuming it doesn't, start uncommenting lines one-by-one until the error shows up again.
Try making a minimal, stand-alone test code example that duplicates the problem (it would help immensely if you did this before posting a SO question).
The simple answer is that your pointers at the start are pointing to somewhere else, either:
You are casting the "scene" structure.
You have junk or unset pointer in the scene structure for normal vector. Could be that you put junk there far before entring the function.
You did notice the 2958875950 is junk/negative integer?

Segfault after repeated reallocs

EDIT: Thanks a lot for the answers. That's right, I will try using vectors instead.
I have a program where I dynamically allocate memory.
The class has an attribute which is an array of structs (**) and also an array of pointers (*) which point to each element of the array of structs, so I make 2 Mallocs. The struct is called "context".
The realloc works fine and doesn't return NULL, but as soon as I have more than 2 elements, the program will give me a segfault when trying to save a value in an element of the array. How can I prevent this segfault?
int my_class::method(uint32_t struct_element)
{
int i= this->numofcontexts;
if(this->local_context_array == NULL)
// That means it is empty and we have to make our first malloc
{
this->local_context_array = (context_t**) malloc(sizeof(context_t*));
*(this->local_context_array) = (context_t*) malloc(sizeof(context_t));
i++;
std::cout << "\n1 Malloc was made of size " << sizeof(context_t)<<"\n";
}
else
// Array is not empty and we have to use realloc
{
this->local_context_array = (context_t**) realloc(this->local_context_array, (i+1)*sizeof(context_t*));
*(this->local_context_array) = (context_t*) realloc(*(this->local_context_array), (i+1)*(sizeof(context_t)));
std::cout << "\n1 Realloc was made of size " << (i+1)*(sizeof(context_t)) <<"\n";
i++;
std::cout << "\nWe now have " << i <<" elements\n";
// As soon as the array is bigger than 2 elements, this gives segmentation fault:
//(this->local_context_array[i-1])->struct_element = struct_element;
}
From the code posted and the symptoms you describe, it seems you do not do this at the end:
this->numofcontexts = i;
If this is true, then every time you call this method, it will find numofcontexts == 0 and local_context_array not NULL, so it will move to your else clause, when it will reallocate the array to i+1 (always 1).
First call will succeed, second call will also succeed with array size of 1 element, and if you try to assign to elements over [0] at this point, you may get a segfault. The reason you might not get a segfault at [1] is usually related to some other variable occupying the space and being trashed but which does not always generate a segfault immediately.

Fortran code calling openCASCADE does not work, pointer hell?

I am sorry for the vague title. This question is a continuation of a previous question posted
here: Using a C++ class object in fortran 77 what I need to do is to reuse the objects created from C++ in Fortran.
The code that I am dealing with is a very simple Fortran code:
C23456
program main
C Pointers to C++ classes. Never use them!
C Just pass them to the C++ functions.
integer*4 shapeToMesh
integer*4 faceMap
integer*4 edgeMap
integer*4 vertexMap
C We have to append //CHAR(0) to the string since it must be
C Null terminated
call readstep('cube.stp'//CHAR(0),isuccess,shapeToMesh)
call createfacemap(shapeToMesh,faceMap)
end
Where the shapeToMesh is a class object that contains the geometry that is parsed from the
input step file. The faceMap edgeMap vertexMap are objects that assign a unique integer to each face edge and vertex respectively
Now the readstep or readstep_ (note that those are C++) function works good and here is the code:
//SuccessInt contains information about successful loading
//of file. 1 for success, 0 for failure
void readstep_(char* inputFile,int* successInt, TopoDS_Shape** shape){
//Print out the filename received from fortan for debug reasons
int len = strlen(inputFile);
std::cout << "Input file ";
for(int i=0; i<len; i++)
std::cout << inputFile[i];
std::cout << std::endl<< std::endl;
//This has a private contructor. So I must first declare
//and then call the constructor.
STEPControl_Reader reader;
reader = STEPControl_Reader();
int succeed = reader.ReadFile(inputFile);
if(!succeed){
std::cout << "There was an error with the input file" << std::endl;
(*successInt) = succeed;
return;
}
reader.NbRootsForTransfer();
reader.TransferRoots();
//Assign memory, then opject
*shape = new TopoDS_Shape();
**shape = reader.OneShape();
(*successInt) = succeed;
return;
}
As you may have already seen from my Fortran snippet, the next thing I want to do is to create a list of my faces present in the shape. To do this I call the createfacemap or createfacemap_ function the code of which is shown below:
void createfacemap_(TopoDS_Shape** shape, TopTools_IndexedMapOfShape** map){
TopoDS_Shape ashape = TopoDS_Shape();
ashape = (**shape);
if(ashape.IsNull())
std::cout << "Shape is null";
*map = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(ashape,TopAbs_FACE,(**map));
std::cout << "Faces: " << (**map).Extent() << std::endl;
return;
}
But instead of 6 Faces I get a result of 0 faces. To investigate any further, I debugged the
program using a point. And the results can be seen in the screenshots
It can be seen that the map variable is initialized and some processing goes on since the
NbBuckets change, however the size does not change at all that means that there are no objects stored. I am using the openCASCADE library. Here are the relevant references:
http://dev.opencascade.org/doc/refman/html/class_topo_d_s___shape.html
http://dev.opencascade.org/doc/refman/html/class_top_exp.html
http://dev.opencascade.org/doc/refman/html/class_top_tools___indexed_map_of_shape.html
any help would be really appreciated!

Invalid heap error when trying to copy elements from a Map to a compatible priority Queue

My program makes a frequency map of characters (which I store in , surprise surprise, a Map), I am trying to copy each element from this map into a Priority Queue so that I can have a sorted copy of these values (I plan to make further use of the Q, that's why am not sorting the map) , but whenever I try to copy these values , the program executes fine for the first two or three iterations and fails on the fourth citing an "Invalid heap" error.
I'm not sure how to proceed from here, so I am posting the code for the classes in question.
#include "srcFile.h"
#include <string>
#include <iostream>
srcFile::srcFile(std::string s_flName)
{
// Storing the file name
s_fileName= s_flName;
}
srcFile::srcFile()
{
// Default constructor (never to be used)
}
srcFile::~srcFile(void)
{
}
void srcFile::dispOverallMap ()
{
std::map<char,int>::iterator dispIterator;
dispIterator = map_charFreqDistribution.begin();
charElement *currentChar;
std::cout<<"\n Frequency distribution map \n";
while(dispIterator != map_charFreqDistribution.end())
{
std::cout<< "Character : " << (int)dispIterator->first << " Frequency : "<< dispIterator->second<<'\n';
currentChar = new charElement(dispIterator->first,dispIterator->second);
Q_freqDistribution.push(*currentChar);
dispIterator++;
// delete currentChar;
}
while(!Q_freqDistribution.empty())
{
std::cout<<'\n'<<"Queue Element : " << (int)Q_freqDistribution.top().ch_elementChar << " Frequency : " << Q_freqDistribution.top().i_frequency;
Q_freqDistribution.pop();
}
}
map_charFreqDistribution has already been populated, if I remove the line
Q_freqDistribution.push(*currentChar);
Then I can verify that the Map is indeed there.
Also , both the Q and the use charElement as the template type , its nothing except the character and its frequency, along with 2 pointers to facilitate tree generation (unused upto this point)
Adding the definition of charElement on request
#pragma once
class charElement
{
public:
// Holds the character for the element in question
char ch_elementChar;
// Holds the number of times the character appeared in the file
int i_frequency;
// Left pointer for tree
charElement* ptr_left;
// Right pointer for tree
charElement* ptr_right;
charElement(char,int);
charElement(void);
~charElement(void);
void operator=(charElement&);
};
class compareCharElt
{
public:
bool operator()(charElement &operand1,charElement &operand2)
{
// If the frequency of op1 < op2 then return true
if(operand1.i_frequency < operand2.i_frequency) return true;
// If the frequency of op1 > op2 then return false
if(operand1.i_frequency > operand2.i_frequency)return false;
// If the frequency of op1 == op2 then return true (that is priority is indicated to be less even though frequencies are equal)
if(operand1.i_frequency == operand2.i_frequency)return false;
}
};
Definition of Map and Queue
// The map which holds the frequency distribution of all characters in the file
std::map<char,int> map_charFreqDistribution;
void dispOverallMap();
// Create Q which holds character elements
std::priority_queue<charElement,std::vector<charElement>,compareCharElt> Q_freqDistribution;
P.S.This may be a noob question, but Is there an easier way to post blocks of code , putting 4 spaces in front of huge code chunks doesn't seem all that efficient to me! Are pastebin links acceptable here ?
Your vector is reallocating and invalidating your pointers. You need to use a different data structure, or an index into the vector, instead of a raw pointer. When you insert elements into a vector, then pointers to the contents become invalid.
while(dispIterator != map_charFreqDistribution.end())
{
std::cout<< "Character : " << (int)dispIterator->first << " Frequency : "<< dispIterator->second<<'\n';
currentChar = new charElement(dispIterator->first,dispIterator->second);
Q_freqDistribution.push(*currentChar);
dispIterator++;
delete currentChar;
}
Completely throws people off because it's very traditional for people to have huge problems when using new and delete directly, but there's actually no need for it whatsoever in this code, and everything is actually done by value.
You have two choices. Pick a structure (e.g. std::list) that does not invalidate pointers, or, allocate all charElements on the heap directly and use something like shared_ptr that cleans up for you.
currentChar = new charElement(dispIterator->first,dispIterator->second);
Q_freqDistribution.push(*currentChar);
dispIterator++;
delete currentChar;
In the above code, you create a new charElement object, then push it, and then delete it. When you call delete, that object no longer exists -- not even in the queue. That's probably not what you want.