Reputation: 1364
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;
}
Upvotes: 1
Views: 694
Reputation: 309
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.
Upvotes: 6
Reputation: 36617
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.
Upvotes: 1
Reputation: 165
Why would you want the declaration of > wt in the IF statement?
Upvotes: -2