IF语句导致分段错误?

时间:2016-01-13 23:43:38

标签: c++ if-statement segmentation-fault

我遇到了一个相当令人困惑的问题。看起来我程序中的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;
    }

3 个答案:

答案 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?