2014-12-05 4 views
0

У меня есть код из проекта, который, похоже, не работает.C++ deque throwing Segfaults

Я пытаюсь сделать deque (of struct), который является статическим членом класса. скелет/основной код выглядит следующим образом (я сохранил все типы данных - my_typedef_fn это тип данных, приобретенный ЬурейеЕ-ки указатель на функцию):

1.h файл:

class A { 
    struct Bstruct { 
     char * b_name; 
     my_typedef_fn b_func; 
    } 
    static std::deque<Bstruct> a_deque; 
    static void func(); 
} 

1.cpp файл:

std::deque<A::Bstruct> A::a_deque; 
void A::func(char * name, my_typedef_fn fn) { 
    a_deque.push_front((Bstruct) {name, fn}); // <<<< segfault ! 
} 

Из моего понимания - The .h файл просто объявляет материал (как обычно) - Первая строка в .cpp инициализирует статический член a_deque - функция func добавляет материал в deque, используя push_back

Но я получаю ошибку сегментации в строке, где вызывается push_front (найденный с использованием gdb).

Кроме того, когда я печатаю a_deque.size() перед push_front я получаю 4294967264 до Segfault И когда я сосчитать число элементов в деке, используя для цикла:

int counter = 0 
for(std::deque<Bstruct> it = a_deque.begin(); it != a_deque.end(); it++, counter++); 

моего счетчик показывает 0 элементов быть в

Итак, я не понимаю, почему я получаю Segfault, ни почему .size() является большой мусор номер

- EDIT 1 - Добавление пути функции называются:

файле 2.cpp

#include "1.h" 
void fn1() { 
    // some code 
} 
A::func("abc", fn1); 

Он выполнил команды:

g++ -c -w -fpermissive -o 1.o 1.cpp 
g++ -c -w -fpermissive -o 2.o 2.cpp 
g++ -o final 1.o 2.o 
+0

Почему бы не использовать 'std :: string' вместо' char * '? Учитывая это, что такое 'имя' и как оно получает свою ценность? Использование char * для строковых данных не так безобидно, как кажется. – PaulMcKenzie

+1

Ваш синтаксис для построения элемента является странным. Вы имели в виду 'Bstruct {name, fn}'? На самом деле, я не знаю, что делает ваш код, или почему он даже компилируется, но это, вероятно, не то, что вы хотите. –

+0

Вы вызываете код из конструктора глобального, что может вызвать доступ к 'a_deque', прежде чем у него будет возможность инициализировать себя? И, пожалуйста, исправьте такие синтаксические глупости, как «A: BStruct». – Angew

ответ

2

Это, как правило, не представляется возможным просто вызвать функцию в глобальном масштабе, как вы показываете в 2.cpp. Но вы упомянули, что код старый, поэтому, возможно, это стандартная вещь или расширение.

В любом случае, вы указали, что функция вызывается в 2.cpp, а статический элемент данных a_deque определен в 1.cpp. Это означает, что вы, вероятно, становитесь жертвой статического фиаско порядка инициализации . Глобалы (например, статические элементы данных и, по-видимому, этот странный автономный вызов функции) инициализируются/выполняются, чтобы они отображались в пределах единицы перевода (= .cpp), но их порядок между единицами перевода не указан.

Это означает, что это вполне возможно для A::func() доступа к a_deque перед конструктором a_deque был бежать, что может вполне возможно, приведет к Segfault (как внутренние элементы данных имеют нулевой дека или, возможно, даже случайные значения).

Чтобы исправить это, вам нужно как-то избавиться от этой ситуации. Одним из вариантов является перемещение всего глобального кода, который может получить доступ к a_deque в 1.cpp и разместить его после определения a_deque.

В качестве альтернативы можно заменить a_deque с функцией-области видимости статической переменной, которая гарантированно будет инициализирован перед первым использованием:

1.h

class A { 
    struct Bstruct { 
     char * b_name; 
     my_typedef_fn b_func; 
    } 
    static std::deque<BStruct>& a_deque(); 
    static void func(); 
} 

1.cpp

#include "1.h" 

std::deque<A::BStruct>& A::a_deque() 
{ 
    static std::deque<BStruct> d; 
    return d; 
} 

void A::func(char * name, my_typedef_fn fn) { 
    a_deque().push_front((Bstruct) {name, fn}); // <<<< hopefully no more segfault 
} 
+0

Это имеет большой смысл! Этот код по существу используется для связывания множества функций с некоторыми именами, поэтому конкретная функция может вызываться, когда пользователь дает конкретное имя. И есть десятки этих функций, которые очень большие и модульные сами по себе (охватывающие 7-8 файлов) ... Можете ли вы предложить другой способ? Вы думаете, что в gcc может существовать флаг для разрешения этого? Или порядок, в котором я использую 1.o или 2.o на последнем этапе компиляции материи? Я знаю, что он работал в 2002 году: P Я бы предпочел не перерабатывать всю структуру – AbdealiJK

+0

@AJK Я добавил альтернативное решение, которое должно работать независимо от глобального порядка инициализации. – Angew

+0

WOAH - EPIC Ответ! – AbdealiJK