我遇到了一个相当令人困惑的问题。看起来我程序中的IF语句导致了分段错误。
我正在使用外部库,并在IF语句中调用外部库中的代码,因此我无法提供这些函数的完整代码,因为我也没有。
发生的事情的基本例子。所以这个例子给我一个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;
}
然而,同样的例子,但没有IF,当我发表评论时,不会导致Segmentation fault
,并且正常执行。
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;
//}
原始示例:
// // 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);
这里发生了什么,这太令人困惑了?
编辑:从此片段调用其他代码的示例
#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);
};
所以这是在第一个IF中构建的。
EDIT2:提供生成可能导致问题的树指针的代码
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;
}
节点的创建方式如下:
static node* InitRoot(int ary){
node *root = new node;
for(int iter = 0; iter < ary; iter++){
root->next.push_back(NULL);
}
return root;
}
答案 0 :(得分:6)
宣布&#39; wt&#39;和&#39; wtrank&#39; if之前的变量。如果在if之后的块内声明它,则其范围仅限于该块。在它超出范围之后,&#39;排名&#39;指针变为悬空,因此稍后访问它可能会导致段错误。
答案 1 :(得分:1)
你的问题几乎可以肯定是其他一些你没有表现出来的代码 - 猥亵指针,从数组末尾掉下来,访问未初始化变量的值等等。
在一些块周围引入if (true)
最多会改变程序的内存布局(例如,如果存储被保留以保存值true
,并且编译器发出一些代码来测试它在执行后续代码之前)。因为内存布局发生了变化,行为不端代码的含义(即被破坏的内容)可能会发生变化。
当然,在这种情况下,可能的更改取决于编译器。积极的优化可能会检测到true
总是(好)true
,因此完全从发出的代码中消除if (true)
。在这种情况下,拥有或不拥有它的程序行为没有区别。但是,并非所有编译器(或编译器设置)都这样做。
顺便提一下,更改定义变量wt
的位置的建议可能会或可能不会因类似原因而起作用。移动定义可能只是改变代码中的动作顺序(机器指令等),或者程序使用的内存布局(特别是如果该对象的构造函数分配了大量资源)。所以它不是一个解决方案,即使它似乎可行。因为它不能保证工作。并且可能会因为(代码,编译器,编译设置等)的其他变化而中断。
问题是,真正的问题可能在于您已经显示的代码(被调用的函数的影响,被调用的构造函数等),或者它可能是在您的程序中先前执行的代码中。这是未定义行为的本质 - 当问题发生时,症状可能不会立即显现,但可能会影响不相关代码的行为。
鉴于问题发生的地方,rank = &wtrank
语句不是原因。原因将在以前的代码中。但是,这个悬空指针将成为后续执行代码的另一个问题 - 一旦解决了这个问题。
答案 2 :(得分:-2)
为什么要声明&gt; IF语句中的wt?