2016-01-13 2 views
0

Я столкнулся с довольно запутанной проблемой. Похоже, что оператор IF в моей программе вызывает у меня ошибку сегментации.Оператор IF, вызывающий ошибку сегментации?

Я работаю с библиотеками extern и вызывая код из внешних библиотек в инструкции 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); 

Что здесь происходит, это так запутано?

EDIT: пример другого кода вызывается из этого 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); 
}; 

Так что это строится в первой ПЧ.

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; 
    } 

ответ

6

Объявите «вес» и ' wtrank "перед if. Если вы объявите его внутри блока, следуя за ним, его область действия ограничена этим блоком. После того, как он выходит за пределы области действия, и указатель «rank» становится свисающим, поэтому доступ к нему позже может вызвать segfault.

+0

Есть ли какое-нибудь обходное решение, чтобы оно все еще могло быть в if? Может быть, используя ссылку? – Whizzil

+1

Висячий указатель относится к объекту 'wtrank'. «Wt» также может оказаться вне вложенной области, потому что его адрес передается конструктору «WTRank». Это не совсем понятно из всего кода. – Blastfurnace

+0

@Whizzil: Ссылка не поможет, они тоже могут болтаться. У вас возникла проблема с продолжительностью жизни вашего объекта. – Blastfurnace

-2

Зачем вам нужно объявление> wt в инструкции IF?

+0

Потому что у меня есть несколько реализаций функции Rank, которые можно использовать. Какой из них используется, определяется как параметр для основной функции. Я редактировал свой пост. – Whizzil

1

Ваша проблема почти наверняка какой-либо другой код, который вы не показали делать что-то неладное - приставать указатель, падающий от конца массива, доступ значение из неинициализированных переменных и т.д.

Вводя if (true) вокруг некоторых блок, самое большее, изменит макет памяти вашей программы (например, если хранилище зарезервировано для хранения значения true, и если компилятор испускает некоторый код для его проверки перед выполнением последующего кода). Поскольку макет памяти изменяется, последствия неправильного кода (т. Е. Того, что сбивается) могут измениться.

Естественно, в этом случае возможное изменение зависит от компилятора. Агрессивная оптимизация может обнаружить, что true всегда (хорошо) true, и поэтому полностью исключают if (true) из испускаемого кода. В этом случае не будет никакой разницы в поведении программы или нет. Однако не все компиляторы (или настройки компилятора) делают это.

Кстати, совет по изменению, где вы определяете переменную wt, может работать или не работать по аналогичным причинам.Перемещение определения может просто изменить порядок действий в коде (машинные инструкции и т. Д.) Или макет памяти, используемый вашей программой (особенно если конструктор для этого объекта выделяет значительные ресурсы). Таким образом, это не решение, даже если оно может работать. Потому что это не гарантируется. И может сломаться из-за других изменений (вашего кода, компилятора, настроек компиляции и т. Д.) В будущем.

Дело в том, что реальная проблема может быть в коде, который вы показали (влияние вызываемых функций, вызываемых конструкторах и т. Д.), Или может быть в коде, выполняемом ранее в вашей программе. Такова природа неопределенного поведения - когда возникает проблема, симптом может не сразу проявиться, а может повлиять на поведение несвязанного кода.

Учитывая, что проблема возникает, заявление rank = &wtrank не является причиной. Причина будет в предыдущем коде. Однако этот обвисший указатель будет другой проблемой для последующего выполнения кода - как только эта проблема будет исправлена.

+0

Позвольте мне привести пример моего «другого» кода, может быть, вы можете сказать мне, что случилось. Конечно, если проблема находится где-то в другом месте, это то, что я собираюсь опубликовать. – Whizzil

+1

Блоки 'if' - это абсолютно проблема. Переменные, определенные внутри этих блоков, уничтожаются, когда они выходят за рамки. Опубликованный код является хорошим примером того, как создать висячий указатель. – Blastfurnace

+0

Ну, скажите мне, как достичь желаемого поведения без оборванных указателей: D – Whizzil

Смежные вопросы