IF statement causing a segmentation error? - c++

I have ran into a rather confusing problem. It seems like the IF statement in my program is causing me a segmentation error.
I am working with extern libraries, and calling the code from external libraries in the IF statement, so I can't provide the whole code of those functions because I don't have it either.
Basic example of what happens. So this example causes me a Segmentation fault.
IRank *rank;
//Generating wavelet tree from BWT with sdsl library
if(true) {
std::cout << "I am in IF" << endl; // this gets printed on the screen
wt_huff<> wt; // right after that - segm fault
construct_im(wt, BWT, 1);
WTRank wtrank(&wt);
rank = &wtrank;
}
However, the same example, but without an IF, when I comment it out, does not cause Segmentation fault, and executes normally.
IRank *rank;
//Generating wavelet tree from BWT with sdsl library
//if(true) {
std::cout << "I am in IF" << endl; // again this gets printed
wt_huff<> wt; // no segmentation error this time
construct_im(wt, BWT, 1);
WTRank wtrank(&wt);
rank = &wtrank;
//}
Original example:
// // Decide what rank function to use
IRank *rank;
if(m_wt) {
// Multiary Wavelet Tree rank function :: student implementation
mwt::node *m_wtree = mwt::generateMultiaryWT(BWT, ary);
MultiWTRank m_wt_rank(m_wtree, ary);
rank = &m_wt_rank;
} else if(b_wt) {
// Binary Wavelet Tree rank function :: SDSL implementation
wt_huff<> b_wtree;
construct_im(b_wtree, BWT, 1);
WTRank b_wt_rank(&b_wtree);
rank = &b_wt_rank;
} else if(non_wt) {
// Implementation of rank function not using Wavelet Tree
LinRank lin_rank(BWT);
rank = &lin_rank;
} else {
// should not happen
}
//...
run(rank);
What happens here, it is so confusing?
EDIT: example of other code being called from this snipper
#include "IRank.h"
#include "mwt.h"
class MultiWTRank : public IRank {
private:
mwt::node *wt;
int n_ary;
public:
MultiWTRank(mwt::node *root, int ary) {
wt = root;
n_ary = ary;
}
~MultiWTRank() {
}
index_type rank(index_type index, symbol_type symbol);
};
So this is being constructed in the first IF.
EDIT2: Providing a code that generates a pointer to the tree that could cause the trouble
class mwt {
public:
// Structure of a MW tree node
typedef struct node {
vector<int> data;
vector<node*> next;
} node;
// ...
static node* generateMultiaryWT(string input, int ary) {
//...
return root;
}
Node is created like this:
static node* InitRoot(int ary){
node *root = new node;
for(int iter = 0; iter < ary; iter++){
root->next.push_back(NULL);
}
return root;
}

Declare the 'wt' and 'wtrank' variables before the if. If you declare it inside the block following the if, its scope is limited to that block. After the } it is out of scope and the 'rank' pointer becomes dangling, so accessing it later may cause a segfault.

Your problem is almost certainly some other code you have not shown doing something untoward - molesting a pointer, falling off the end of an array, accessing value of an uninitialised variable, etc.
Introducing an if (true) around some block, at most, will change memory layout of your program (e.g. if storage is set aside to hold the value true, and if the compiler emits some code to test it before executing the subsequent code). Because the memory layout changes, the implications of misbehaving code (i.e. what gets clobbered) can change.
Naturally, in this case, the possible change depends on the compiler. An aggressive optimisation may detect that true is always (well) true, and therefore eliminate the if (true) entirely from emitted code. In this case, there will be no difference on program behaviour of having it or not. However, not all compilers (or compiler settings) do that.
Incidentally, the advice to change where you define the variable wt might or might not work for similar reasons. Moving the definition might simply change the order of actions in code (machine instructions, etc), or the layout of memory as used by your program (particularly if the constructor for that object allocates significant resources). So it is not a solution, even if it might appear to work. Because it is not guaranteed to work. And may break because of other changes (of your code, compiler, compilation settings, etc) in future.
The thing is, the real problem might be in code you have shown (impact of functions being called, constructors being invoked, etc) or it might be in code executed previously in your program. Such is the nature of undefined behaviour - when a problem occurs, the symptom may not become visible immediately, but may affect behaviour of unrelated code.
Given where the problem occurs, the rank = &wtrank statement is not the cause. The cause will be in previous code. However, that dangling pointer will be another problem for subsequently executed code - once this problem is fixed.

Why would you want the declaration of > wt in the IF statement?

Related

Memory allocation error when attempting to print contents of a tree in C++

My problem probably has a simple solution that is staring me in the face, but so far I have been unable to find it. I am pretty new to C languages and this is the first program I have written in C++.
I have a function create_complete_tree(int nr_child_nodes, int tree_depth) that makes a tree of depth int tree_depth in which each node (except for the last row) has int nr_child_nodes number of child nodes. create_complete_tree(2,4) makes a tree that starts out like this:
1
/ \
/ \
2 9
/ \ / \
3 6 10 13
/\ /\/\ /\
...
I am trying to make a function print(std::ostream& str) that, when called on the root node of the tree above, prints the tree contents in this format:
node_1
node_2
node_3
node_4
node_5
node_6
node_7
node_8
node_9
node_10
node_11
node_12
node_13
node_14
node_15
I will worry about adding the indents later, but right now I'm just focused on printing the nodes out in the correct order. This is what I have so far:
void node::print(std::ostream& str) {
str << this->get_name() << std::endl;
for (int i = 0; i < this->get_nr_children(); i++) {
node child = (*this->get_child(i));
child.print(str);
}
}
This function prints nodes 1-8 out, but then I get a Segmentation fault: 11 error. I know this error is a result of attempting to access memory that is somehow unavailable/off-limits, but I'm struggling to understand what that really means in my case. My create_complete_tree method looks like this:
void node::create_complete_tree(int nr_child_nodes, int tree_depth) {
if (tree_depth == 1) {
return;
} else {
while (this->get_nr_children() < nr_child_nodes) {
node* new_child = new node();
this->add_child(new_child);
(*new_child).create_complete_tree(nr_child_nodes, tree_depth - 1);
}
}
}
The child node pointers for each node are stored in a vector called child_nodes. Thanks for taking the time to read this. I'd be grateful for any responses that help me find a solution and better understand memory allocation.
Problem
This code very probably infringes the rule of 3. The following statement:
node child = (*this->get_child(i));
creates a clone of the node. If you didn't provide for the rule of 3, but implemented the destructor, the clone will use the same pointers to the same children than the original node. Unfortunately, when you then leave the print() function, the clone gets destroyed and the destructor will destroy the children. All subsequent access to these children will then access an object which no longer exist, which is UB.
Segfault is a possible symptom of UB. I cannot confirm for sure without seing the constructor, copy constructor, assignment and destructor implementation of node. But seing this code, and many similar questions here, I would be surprised that it'd be another issue ;-)
Potential solutions
The correct solution would anyhow be to implement what's missing for the trule of 3. Because you will experience similar problems in many situations if you don't.
Another solution (which is not mutually exclusive) would be to use pointer without cloning:
void node::print(std::ostream& str) {
str << this->get_name() << std::endl;
for (int i = 0; i < get_nr_children(); i++) { // this-> is not needed
node *child = this->get_child(i); // pointer assignment without cloning
child->print(str); // member invokation for a pointer
}
}

What exactly is causing my node class with a vector housing the pointers of the class to cause segmentation faults?

Currently I'm just starting off with creating nodes for my tree. The idea I had in mind was to simply create something like this:
class Node
{
private:
int key_;
std::vector< Node * > child_;
public:
Node(int key)
: key_(key), child_()
{
}
Node * get_child(int key) const
{
return child_[key];
}
};
Nothing too fancy, right?
Inside the main, I call all the header files and have initialized the whole entire thing like this
Node child(0);
What causes some frustration right now is when I try to simply just check if everything in my node is truly initialized. All I'm doing in the main is this.
std::cout << node.get_child(0) << std::endl;
The dreaded segmentation fault error comes up which means that the memory allocation of the vector is off. My question is this, if this is actually what's happening, what in my code is wrong so far? If it is not, please clarify on what exactly in my class template is wrong.
In the constructor for Node, you set the internal key value, and construct an empty vector. You don't have any code shown that adds anything to the vector, and trying to access element 0 of an empty vector results in Undefined Behavior (a crash, in your case).
You probably want something like child(1) (to create one node in the vector), child(key + 1, nullptr) (to create null node pointers so that elements in the 0..k inclusive range are valid) or a loop in the constructor to set actual nodes into the vector.

Something looks wrong in this implementation of stack but it works fine

I have this assignment where I need to implement a stack using arrays (easy as you like) but three of the methods have already been provided and I just need to implement the remaining two functions: peek() and flush().
However, I don't quite seem to agree with the implementation of pop provided.
I mean, when you pop without any elements inside (N == 0), then it would mean something like Array[-1] and the program should crash but it doesn't. Please explain how this (not crashing) happens.
class STACK {
private:
int* s;
int N;
public:
STACK(int maxN) {
s = new int[maxN];
N = 0;
}
int empty() const {
return N == 0;
}
void push(int item) {
s[N++] = item;
}
int peek() {
/* implement this part */
}
int pop() {
return s[--N];
}
void flush() {
/* also implement this part */
}
};
I don't quite seem to agree with the implementation of pop provided.
It has a pre-condition: it must not be called if the stack is empty. Whether to enforce that precondition (with a runtime cost to check it) or just document it (with a risk of invalid behaviour) is a design decision for you to make.
Please explain how this (not crashing) happens.
Undefined behaviour doesn't necessarily cause the program to crash. If there's addressable memory before the array, then s[--N] will (almost certainly) just read what's there. If there isn't, then it might crash.
You're right. The pop function as written will fail when the stack is empty.
Accessing data prior to the start of an array is undefined behavior, which does mean exactly that. It can do anything including not crashing.

Find an edge using the Ford Fulkerson algorithm?

I'm trying to implement the Ford Fulkerson Algorithm in C++.
However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.
This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.
//An object of this class represents an edge in the graph.
class Edge
{
private:
//Node *prev;
public:
int flow;
Edge(Node *firstNode, Node *secNode, unsigned inCost) {
orgNode = firstNode;
dstNode = secNode;
bridge_capacity = inCost;
}
Edge() {
flow=0;
}
};
//An object of this class holds a vertex of the graph
class Node
{
public:
Node *prev;
vector<Edge>& getAdjNodeList() {
return adjNodeList;
}
};
Edge *find_edge(Graph *g,Node *from,Node *to) {
vector<Edge> b=from->getAdjNodeList();
for(int i=0;i<b.size();i++) {
if(b[i].getDstNode()==to)
return (&b[i]);
}
return NULL;
}
int my_alg(Graph *as,Node *source,Node *sink){
Edge *find_edge();
int max_flow=0;
while(bfs(as,source,sink)) {
Node *b=as->nodeList[num_isl];
int inc=100000000;
while(b->prev!=NULL) {
Edge *bok=find_edge(as,b->prev,b);
inc=min(inc,bok->get_bridge_capacity()-bok->flow);
b=b->prev;
}
b=as->nodeList[num_isl];
while(b->prev!=NULL){
Edge *bok = find_edge(as,b->prev,b);
bok->flow += inc; // This is the place the flow is incremented
bout << bok->flow; // Here, everything is alright.
bok = find_edge(as,b->prev,b);
cout << bok->flow; // However, this is is not the correct result.
}
max_flow+=inc;
}
return max_flow;
}
I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.
If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:
class Edge {
public:
int flow;
};
class Node {
private:
vector<Edge> adjNodeList; // list of outgoing edges for this vertex
public:
vector<Edge> & getAdjNodeList() {
return adjNodeList;
}
void addAdjNode(Node* newAdj) {
adjNodeList.push_back(Edge(newAdj));
}
};
int main() {
Node *node1 = new Node();
Node *node2 = new Node();
node1->addAdjNode(node2);
vector<Edge> t = node1->getAdjNodeList();
vector<Edge> f = node1->getAdjNodeList();
t[0].flow = 11;
cout << t[0] << endl;
cout << f[0] << endl;
}
If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.
What is happening here? When calling
vector<Edge> t = node1->getAdjNodeList();
the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.
To get around this problem, you could just have done the following:
vector<Edge> & t = node1->getAdjNodeList();
which saves the reference and does not create a new object.
I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.
It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).
Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.
Hope I could help.

Strange seg fault with function pointer returning a value

While learning C#, I found it fun to reimplement things like List or LinkedList just to understand how it works and potential problems you may have while implementing it.
While learning C++, since I have some experience in C#, I decided to challenge myself and attempt to implement more advanced code than what the end of chapter activities ask. So, I ended up trying to implement a non generic list in C++ to try it out, but ended up receiving a very weird seg fault.
A small disclaimer on the code, while trying to fix it I ended up refactoring it and removing stuff (none of it changed the error, though) so a function or two has no use but after a few hours trying to understand the problem, I don't want to remove or change anything and accidently fix the problem. Anyway, here's the code.
class List {
private:
int *ListData;
size_t ListSize;
size_t Pos;
std::stack<size_t> NullList;
size_t InternalNull();
inline size_t PosOnly();
void Check();
size_t (List::*NextNumber)();
public:
List(bool InternalNullHandle);
List(size_t DefaultSize, bool InternalNullHandle);
~List();
void Add(const int SalesRef);
int GetCopy(size_t Pos);
int Get();
};
List::List(bool InternalNullHandle) {
NextNumber = (InternalNullHandle) ? &List::InternalNull : &List::PosOnly;
ListSize = 32;
ListData = new int[32];
Pos = 0;
}
List::List(size_t DefaultSize, bool InternalNullHandle) {
NextNumber = (InternalNullHandle) ? &List::InternalNull : &List::PosOnly;
ListSize = DefaultSize;
ListData = new int[DefaultSize];
Pos = 0;
}
List::~List() {
delete[] ListData;
}
void List::Check() {
if (Pos >= ListSize) {
size_t OldSize = ListSize;
ListSize*=2;
int *Buffer = new int[ListSize];
memcpy(Buffer, ListData, sizeof(int)*OldSize);
if (ListData != NULL) {
delete[] ListData; //POINT OF INTEREST ONE
ListData = NULL;
}
else {
std::cerr<<"ListData is null."<<std::endl;
}
ListData = Buffer;
}
}
size_t List::InternalNull() {
if (NullList.size() != 0) {
size_t ToReturn = NullList.top();
NullList.pop();
return ToReturn;
}
return PosOnly();
}
inline size_t List::PosOnly() {
size_t Old = Pos;
++Pos;
Check();
return Old;
}
inline void List::Add(const int SalesRef) {
//size_t Value = (this->*NextNumber) ();
//ListData[Value] = SalesRef;
//if the above code is utilised instead, everything works fine
ListData[ (this->*NextNumber) () ] = SalesRef; //POINT OF INTEREST TWO
}
inline int List::GetCopy(size_t Pos) {
return ListData[Pos];
}
I normally don't post, but google extensively. I ended up installing and running valgrind, which gave read and write errors at Point of Interest One when Point of Interest Two was used. However, when Point of Interest Two was commented out and the commented lines were used, no problems were given.
The problem only arises after 128 iterations, meaning it doubles to 64 and 128 correctly as well as deleted the arrays correctly.
Also, as a note, the code ran perfectly fine on Windows compiled with g++.
I tried to reproduce the error using a separate class, but it worked perfectly fine.
Again, I know I should use the standard containers (and I will) but I like to understand everything and the fact that I can't figure this out is extremely annoying. Coupled with the fact that I can't even reproduce it and had to copy this incomplete and badly designed code just makes it worse. Thanks for the help in advance!
Minor edit, if it's really hard to read I'll add comments and try to clean the code up without breaking (well, fixing, rather) it. The OSes it was tested on was Windows 7 with mingw (which worked) and Debian with g++ (which only worked with the commented lines uncommented).
The problem with the statement
ListData[ (this->*NextNumber) () ] = SalesRef; //POINT OF INTEREST TWO
is that there's no sequence point between fetching the value of the field ListData and calling the member function pointed at by NextNumber. So the compiler is perfectly happy doing that load before the function call and then doing the indexing off of it after the call. However, that call may result in reallocating ListData, so the pointer it got from before the call is now dangling (it points at the just deleted array) and bad things happen.
With the commented out code, you force the function call to occur before the fetch of ListData, so that fetch will always get the right value after the resize reallocation.