c++ NULL terminated array segfault - c++

I am writing a program that splits graphs, I got a class
Graph and an Algorithm class. I compute the partitioning in my Algorithm class and split the graph with a method in the Graph class according to the partitioning.
My code looks like this:
In my GraphClass:
void bisectGraph(int *iPartitioning, Graph **Subgraphs, Edge **Separator){
...
// Store separators in an array
Separator = new Edge*[Separators.size()+1]; //Separators is a vector containing the separating edges
if(Separator == NULL)
writeErrorMsg("Error assigning memory.", "Graph::bisectGraph");
for(i=0, SepIter = Separators.begin(); SepIter != Separators.end(); i++, SepIter++)
Separator[i] = *SepIter;
Separator[Separators.size()] = NULL;
}
In my Algorithm clas I call it like this:
Edge** separators;
Graph** subgraphs;
int somePartitioning;
g->bisectGraph(somePartitioning, subgraphs, separators);
Works fine so far, but when I want to work on my separators array like this for instance:
for(int i=0; separators[i]!=NULL, i++){
...
}
I always get a segmentation fault. ddd tells me that at the end of bisectGraph separators contains some content. Since I can't find any other mistake I think i got some concept wrong?

The new value of Separator is not being propagated to the separators variable outside the function call. Even though it has type Edge ** you're assigning to it inside the function, but that only assigns to the function's copy of the variable. Remember that C++ is pass-by-value unless otherwise specified.
You could change the signature to Edge **&, but it'd be more sensible to use a vector, and take a parameter of type vector<Edge *> &.

Related

Previous content of std vector is replaced during iteration

I am writing a program which is supposed to find a rooted spanning tree in a graph and all the unique paths joining the root with the other vertices in the spanning tree. I am trying to perform both operations with one function only:
void Spanning_tree_finder(){
int * v=Add_edges(s1); int control=0; int size;
for(int i=0; i<_g.GetE(); i++){
if(control==0 && v[i]==1) {
s1[i]=1; control=1;
size=_v.size();
for(int j=0; j<size; j++){
if(_v[j].Getv2()==_g.GetEdge1(i)){
Path pnew=_v[j];
pnew.Setv2(_g.GetEdge2(i));
pnew.Setp(i);
_v.push_back(pnew);
};
if(_v[j].Getv2()==_g.GetEdge2(i)){
Path pnew=_v[j];
pnew.Setv2(_g.GetEdge1(i));
pnew.Setp(i);
_v.push_back(pnew);
};
};
Spanning_tree_finder();
};
};
return;
};
For the sake of context, the function builds a spanning tree iteratively, which at the end of the process is contained in s1, by taking a tree, also contained in s1, searching all the adjacent edges using the function Add_edges and adding thus to the previous tree one of the adjacent edges. Then the function is called again (note that both Add_Edges and Spanning_tree_finder are part of a class and s1 is a private member of such class). During this process, the function also constructs the path joining the root with the loose vertex associated with the newly introduced adjacent edge by searching for a previous path joining the root with the non-loose vertex of the newly introduced edge and adding to this path the newly introduced edge. The paths are all stored in a vector of paths, _v. I know this explanation is a bit convoluted but I hope it is clear.
However, there is a problem with this function, since it seems that at every iteration all the paths contained in _v are substituted with the path which was obtained in the current iteration. Instead of obtaining _v.size() different paths, _v contains _v.size() copies of the same path, and this holds at every iteration. I don't understand why this would happen, since it seems to me that the function never accesses previously-added elements.
I hope the problem as I explained is clear, and I am happy to provide any further clarification.
EDIT: More specifically, the lines of codes which I think are problematic are
for(int j=0; j<size; j++){
if(_v[j].Getv2()==_g.GetEdge1(i)){
Path pnew=_v[j];
pnew.Setv2(_g.GetEdge2(i));
pnew.Setp(i);
_v.push_back(pnew);
};
if(_v[j].Getv2()==_g.GetEdge2(i)){
Path pnew=_v[j];
pnew.Setv2(_g.GetEdge1(i));
pnew.Setp(i);
_v.push_back(pnew);
};
};
The core of the problem is how pnew is inserted in _v. Instead of the element pnew being added at the end of the vector, all the elements in _v are substituted with pnew
Sure sounds like the objects in _v have some data accessed by pointer, and that you are modifying the objects already in _v by modifying an object you think is new.
Crystal ball says Path pnew = _v[j] copies an existing Path object, which contains some pointers to data. The pointers will be copied to the new object, but point to the same location, so modifiers like Setv2 and Setp will change the data for all of them.
Try fixing Path by either replacing the explicit pointers with something else, like vectors, or write a proper copy-constructor and assignment operator that deal with those pointer fields correctly (by allocating new memory and copying the contents).

Heterogeneous container of base class when the derived instances are not pointers

I have a base class and I want to store instances of its derivatives in a collection of some sort.
At first I created a map:
std::map<int, Variable> varriableItems;
and then ussing templates I created functions for each derivative and I tried passing in the derivatives like so:
template <>
void Array::addToMap<Number>(Number input)
{
numberVariables[itemCount_] = input;
itemCount_++;
}
By doing so this function was not called because everything was of type Variable of course and I found out about slicing.
So instead I changed my map to take in pointers to my base class
std::map<int, Variable*> varriableItems;
but the problem I have is that all my objects are not created as pointers so I could not pass them in and I was getting errors.
No suitable conversion from "Number" to "Variable" exists.
Due to my implementation I can only create instances of objects
like so:
auto aNumberVariable = Number{50};
Ofcourse if I instead do:
Number aNumberVariable = new Number(50);
it works great.
The reason am doing this is explained bellow.
Please bear with me because this is a weird assignment.
We were asked to create a program that behaves/understands the syntax of a programming language called Logo, without actually analyzing the text as an input file, but rather "disguise" it to appear as such while in fact we just use C++ using what we learned from C++ and lots of overloads and pre-processor tricks
We have to be able to make our own "types" of variables called NUMBER,WORD,BOOLEAN,ARRAY, LIST,SENTENCE.
To declare them we have to use(note no semi-colons should be used):
//define number variable with value 21
MAKE number = NUMBER: 21
//define hello variable with value “hello”
MAKE hello = WORD: “hello”
//define myMoves variable contains list of turtle moves
MAKE myMoves = LIST [
LIST [WORD: “FORWARD”, NUMBER: 100],
LIST [WORD: “LEFT”, NUMBER: 90],
LIST [WORD: “FORWARD”, NUMBER: 100]
]
//define array variable with empty array
MAKE array = ARRAY {
number,
hello,
NUMBER: 12
BOOLEAN: TRUE,
ARRAY {
myMoves,
LIST [WORD: “BACK”, NUMBER: 100]
}
}
//define book variable with sentence type
MAKE book = SENTENCE (hello, WORD: “hello!”)
That's just a small part, we later have to support functions, nested loops , etc.
So do this I have to find a way to use the colon since I cannot overload it, so I did this:
//Create an instance of Number and write the first half of the ternary operator so we
//always get the false value so we can use the : like this
#define NUMBER Number{} = (false) ? 0
//semicolon infront for the previous command that needs it
#define MAKE ;auto
So now this:
//following commands will deal with the semicolon
MAKE myNumber = NUMBER: 21
worked great and it actually gets replaced by the processor to this:
auto myNumber = Number{} = (false) ? 0 : 21
So i worked with this for all my derivatives and I proceeded to overload operators to compare them, implement if else function in a similarly weird syntax.
Now I either have to figure out a way to make this work again but this time creating them as pointer instead (Which I assume is the only way for this to work, but I so far I couldn't figure it out) or create a single class for all types but doing it in separate objects that all inherit from a single base class makes more sense to me.
And am not sure how strict they will be, it is an unconventional project assignment for sure.
The reason I want to hold them together in a container is so I can then implement an Array and list object that can hold every type. At first I tried to use a different container for each type and made an iterator to iterate multiple maps separately, but when I got to the LIST implementation things got weird.
The list syntax is using the brackets [ ] which can only get 1 input value, so the idea was to collect them by overloading the comma operator and pass in one value to the list object.
I know this is weird , thank you for your time
I didn't read through all of your post. (actually I did because your task is so ... beyond words) but if you need polymorphism in a container and you also need the container to hold the objects, then the solution is unique_ptr:
container<std::unique_ptr<Base>>
In your case it would go something along this:
std::unordered_map<int, std::unique_ptr<Variable>> varriableItems;
varriableItems[0] = std::make_unique<Number>(50);

C++ passing by reference in constructor

So I am making a program in C++ and my main method has to construct an object that takes as a parameter a vector.
This is my code:
int main() {
vector<Seller> *staff = new vector<Seller>;
for (int i = 0; i < 50; i++) {
staff->push_back(Seller(i));
}
BookStore store(*staff);
deque<Book> books;
books = store.getBooks();
}
So, these are some pretty simple Object-Oriented concepts I think.
My goals are:
First, initializing an empty vector of sellers. A Seller is an object that has a constructor:
Seller(int i);
And represents, of course, a seller.
Then, I want to fill in the vector with actual Sellers. These are constructed in the for loop.
Then, I want to create a Store, which takes as an argument the sellers that work there.
Finally, I create a new deque called books, and I assign to it the value of books in the Store class. The initialisation of the Books deque is done in the constructor of the Store:
Store::Store(vector<Seller> &sellers) {
this->sellers = sellers;
this->books = deque<Book> (100, "Harry Potter");
}
So this is the code and I am wondering if I am making a mistake in the passing arguments to new constructors part.
I am a bit confused when passing by reference so I am asking for a bit on help on that part. I have two main questions:
1) Are there any errors there, considering how I want to run my program? Consider also that in the rest of the main method (not included here) I constantly change the value of the books deque.
2) Is there any way to replace an element in a deque without having to erase and insert?
Is there a built-in function replace? If not, is the below code going to work if I just want to replace a value in the deque?
For example, if the deque is like that:
3 4 5 2
And it (an iterator) has value 2.
Then I want the deque to become:
3 4 6 2
When doing:
books.erase(it);
books.insert(it, 6);
Thanks for any tips or help!
OK, here a short analysis.
Firstly, the unique real error I found: staff is defined as a pointer and is given a value with new but is never released. You should anyway avoid using raw pointers, so either create the object on the stack:
vector<Seller> staff{};
or use a smart pointer
auto staff = make_unique<vector<Seller>>{};
(you will then have to learn something about the ownership semantics, so as you still are a beginner I'd recommend the first solution).
Then, notice how the line
this->sellers = sellers;
in Store::Store will make a copy of the sellers vector, which probably is not what you meant. If you wanted your store to reference the variable created on main(), you should redefine your Store as
class Store {
// ...
vector<Seller>& sellers;
//...
};
and the constructor as
Store::Store(vector<Seller> &sellers) :
sellers{sellers} // reference member variables must be given a value before the body of the constructor begins
{
books = deque<Book> (100, "Harry Potter");
}
For the same reason, your line
books = store.getBooks();
will make a copy of the deque (but maybe in this case it was intended).
Finally, C++ offers many container manipulating functions under the <algorithms> library. Take a look at the reference. But if you already have an iterator to the element you want to replace, you do not need such algorithms, just write:
*it = 6;

How to traverse a recursive variant vector using Boost C++

I want to build a vector tree constructed as follows
struct myStruct {
int a;
string b;
};
typedef boost::make_recursive_variant<
myStruct *
, std::vector< boost::recursive_variant_ >
>::type myStruct_tree;
If I append a multiple vectors, and vectors in those vectors, how would I traverse the tree using some kind of position vector
vector<int>
Which locates the objects position in each vector/subvector defined in the vector pointer tree.
I'm not 100% sure I understand your question, so please clarify if I get something wrong. I'm assuming the vector is a path, with each element giving the index of the element to move to. With that in mind, I'd try something like this:
myStruct_tree t = ...;
myStruct_tree* tit = &t;
for(iterator pit=path.begin(); pit!=path.end(); ++pit)
{
// retrieve branches at current position
vector<myStruct_tree>& vec = get<2>(*tit);
// get next position in tree, will throw on bad index
tit = &vec.at(*pit);
}
assert(tit);
// retrieve the leaf at the final position
myStruct* res = get<1>(*tit);
Notes:
Using an unsigned integer for the indices would be a bit more natural to me.
vector::at() throws an exception on out-of-range.
I haven't looked up the exact syntax of how to get an element of the variant. With the version get<1>(*tit); I used above, I meant the one that retrieves the first element (i.e. the myStruct pointer). Further, it should be the one that returns a reference or throws in order to handle errors.
Consider replacing the range-checking with your own code in order to provide better diagnostics. I didn't do it to keep the structure of the algorithm clear.

no suitable conversion from "std::string" to "char" exists

I'm working on a project for school and I am running into a bit of a problem (error is in the title).
Here is the line of code that runs into the error:
kruskalS[n].nodeList[m].push_back(tempFirstCity);
kruskalS is a struct and nodeList is a vector of type string within the struct and I'm trying to insert tempFirstCity (also a string) into that array.
I could easily be making a basic mistake since I haven't done any programming since April. Any kind of help would be appreciated and I'm willing to post a bit more information from the program if needed.
A std::string is (sort of) a container of chars. A push_back function is used to add one element to the end of a container. So when you call kruskalS[n].nodeList[m].push_back(tempFirstCity);, you say you are trying to add one element to the end of the string called kruskalS[n].nodeList[m]. So the compiler expects that one element to be a char.
If you know that tempFirstCity is not empty and you want to add the first char from tempFirstCity to the end of kruskalS[n].nodeList[m] (including the case where you know tempFirstCity.size() == 1), you can do
kruskalS[n].nodeList[m].push_back(tempFirstCity[0]);
If you want to add the entire string after any current contents, you can do
kruskalS[n].nodeList[m] += tempFirstCity;
If you expect there are no current contents and/or you want to just replace anything already there with the tempFirstCity string, you can do
kruskalS[n].nodeList[m] = tempFirstCity;
You can use:
std::string::c_str()
It returns a const char *.
You say nodeList is an array of type string. i.e. std::string nodeList[x] where x is a constant.
Then assigning a new element to that array where m < x is as follows:
kruskalS[n].nodeList[m] = tempFirstCity;
Based on comments:
For appending to end of vector you don't need the index m:
kruskalS[n].nodeList.push_back(tempFirstCity);
For inserting at index m:
vector<string>::iterator itr = nodeList.begin();
for (int i = 0; i < m; i++)
itr++;
nodeList.insert(itr, tempFirstCity);
In C++, you can use string::c_str() to convert a string to C programming char array..