2016-06-15 5 views
1

私は、ミューテックスで保護されているすべては、次のような機能でSTLのmap、上の操作を実行します - 私は、セグメンテーションを得たとSegfaultが原因プロセスの終了時に静的変数のクリーンアップに見つける

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

releaseコールバックでeraseコールが発生する可能性が最も高いのは、マップにアクセスできない唯一のアクセスポイントですガーディング機構その時点でWatchCtxが地図のキーの一部であることは確かですか?そうでない場合は、インサートがすでに外されている可能性があります。 しかし、Velkanがすでに言ったように、valgrind(またはあなたのデバッガ)が確実にあなたに与えるでしょう。

+1

それはunique_lockによって保護されていませんか?たぶん私はその動作を誤解しているかもしれない –

+0

@Bug Killerロックは同時に複数のアクセスからマップを保護します。それはあなたがそれが最初に(たとえば、それが決して適切に追加されたことがない)地図にないことを与えるキーから保護しません。私は、プログラムの文脈と呼び出しの制約が、それを検証したり、偽ったりするのに十分であるかどうかはわかりません。 'erase'を呼び出す前に' find'を使ってキーをチェックしてエラーが発生しなくなったら、あなたの挿入ルーチンか、いつ 'WatchCtx'を削除するかを決めてください。 – starturtle

+0

存在しないキーで消去を呼び出すのが安全だと思います:[695754] –

関連する問題