2016-06-15 10 views
1

я делать операции на карте STL в следующих функциях, все из которых находятся под защитой мьютекса: -Segfault в C++ STL карты найти из-за статическую переменную очистку во время завершения процесса

static std::mutex track_active_lock_mtx; 
typedef intrusive_ptr<WatchCtxInternal> WatchCtxInternal_h; 
static std::map<WatchCtxInternal*, WatchCtxInternal_h> actives; 
void* get_ptr(WatchCtxInternal_h ctx) 
{ 
    unique_lock<mutex> trackActiveLock(track_active_lock_mtx); 
    if(actives.find(ctx.get()) == actives.end()) { 
     actives.insert(make_pair(ctx.get(), ctx)); 
    }  
    trackActiveLock.unlock(); 
    return ctx.get(); 
} 

void genericWatcher(void *watcherCtx) 
{ 
    unique_lock<mutex> trackActiveLock(track_active_lock_mtx); 
    auto it = actives.find((WatchCtxInternal*)watcherCtx); 
    if (it == actives.end()) {   
     return; 
    } 
    //do unrelated stuff 
    actives.erase(it); 
} 

я получил сегментацию ошибка в первой функции: -

Program terminated with signal SIGSEGV, Segmentation fault. 
#0 _M_lower_bound (this=<optimized out>, __k=<optimized out>, __y=0xf31256e8, __x=0x65687465) at /volume/evo/files/opt/poky/1.8.2-4/sysroots/i586-poky-linux/usr/include/c++/4.9.2/bits/stl_tree.h:1261 
1261   if (!_M_impl._M_key_compare(_S_key(__x), __k)) 
(gdb) bt 
#0 _M_lower_bound (this=<optimized out>, __k=<optimized out>, __y=0xf31256e8, __x=0x65687465) at /volume/evo/files/opt/poky/1.8.2-4/sysroots/i586-poky-linux/usr/include/c++/4.9.2/bits/stl_tree.h:1261 
#1 find (__k=<optimized out>, this=0xf6ac8e2c <actives>) at /volume/evo/files/opt/poky/1.8.2-4/sysroots/i586-poky-linux/usr/include/c++/4.9.2/bits/stl_tree.h:1913 
#2 find (__x=<optimized out>, this=0xf6ac8e2c <actives>) at /volume/evo/files/opt/poky/1.8.2-4/sysroots/i586-poky-linux/usr/include/c++/4.9.2/bits/stl_map.h:860 
#3 get_ptr (ctx=...) 
(gdb)fr 3 
(gdb) p ctx 
$4 = {px = 0xf3124d30} 

EDIT: Мне удалось получить трассировку стека с помощью инструмента Memcheck. То, что происходит в том, что Статическая карте очищаетса в рамках завершения процесса, но обратный вызов genericWatcher происходит в другом потоке до полного выхода: -

main.cpp

static void thread1(void *arg) { 
    //call genericWatcher repeatedly 
} 

int main() { 
    if(fork() == 0) { 
     pthread_create(..., thread1,..) 
     //call get_ptr() repeatedly 
    } 
    return 0; 
} 

Есть ли любым способом предотвратить это? Я мог бы выделить синглтон, который содержит карту активных веществ, но я стараюсь избегать использования одиночек

+2

Valgrind this ... – Velkan

+0

не удалось воспроизвести с текущим модульным тестом –

+1

Ваш примерный код должен быть минимальным, но полным! Никто не может воспроизвести ваши проблемы. –

ответ

0

Наиболее вероятная точка отказа является erase вызовом в вашем release обратного вызова, потому что это единственная точка доступа к вашей карте, что не получило любой защитный механизм. Вы уверены, что ваш WatchCtx является частью ключей карты? Если нет, возможно, что вставка уже отпустила. Но, как уже сказал Велкан, valgrind (или ваш отладчик выбора) даст вам определенность.

+1

Не защищен ли он уникальным_блоком? Возможно, я неправильно понял, как это работает –

+0

@Bug Killer блокирует защиту карты от множественного доступа в одно и то же время. Он не защищает его от ключа, который вы ему даете, а не на карте, чтобы начать (например, если он никогда не был добавлен должным образом). Я не знаю контекста программы и вызывающих ограничений достаточно, чтобы проверить или фальсифицировать это. Если вы проверите ключ с помощью 'find' перед вызовом' erase' там и ошибка прекратится, я бы посмотрел ваши подпрограммы ввода или то, как вы определяете, какой 'WatchCtx' вы удаляете, когда. – starturtle

+0

Я думаю, что удаление звонков с несуществующим ключом безопасно: [695754] –