2014-02-14 25 views
-1

這是關係到這個問題,我已經在這裏問:c++ : filling map of maps via map instance allocation from a vector of maps並沒有得到解決......在所有提供C++地圖錯誤的地圖,可能涉及分配器

的代碼有..錯誤消息(與此更新錯誤的第一個重要部分,我忘記報告):

Program received signal SIGSEGV, Segmentation fault. 
0x0804f9d4 in __gnu_cxx::new_allocator<std::pair<char* const, int> >::construct (this=0xbffff06f, __p=0x8057428, __val=...) 
at /usr/include/c++/4.6/ext/new_allocator.h:108 
108  { ::new((void *)__p) _Tp(__val); } 



(gdb) backtrace 
#0 0x0804f9d4 in __gnu_cxx::new_allocator<std::pair<char* const, int> >::construct (this=0xbffff06f, __p=0x8057428, __val=...) 
at /usr/include/c++/4.6/ext/new_allocator.h:108 
#1 0x0804f38e in std::_Rb_tree<char*, std::pair<char* const, int>, std::_Select1st<std::pair<char* const, int> >, std::less<char*>, std::allocator<std::pair<char* const, int> > >::_M_create_node (this=0x8098d1c, __x=...) at /usr/include/c++/4.6/bits/stl_tree.h:381 
#2 0x0804e209 in std::_Rb_tree<char*, std::pair<char* const, int>, std::_Select1st<std::pair<char* const, int> >, std::less<char*>, std::allocator<std::pair<char* const, int> > >::_M_clone_node (this=0x8098d1c, __x=0xfffffffd) at /usr/include/c++/4.6/bits/stl_tree.h:427 
#3 0x0804c5e5 in std::_Rb_tree<char*, std::pair<char* const, int>, std::_Select1st<std::pair<char* const, int> >, std::less<char*>, std::allocator<std::pair<char* const, int> > >::_M_copy (this=0x8098d1c, __x=0xfffffffd, __p=0x8098d20) at /usr/include/c++/4.6/bits/stl_tree.h:1036 
#4 0x0804bd45 in std::_Rb_tree<char*, std::pair<char* const, int>, std::_Select1st<std::pair<char* const, int> >, std::less<char*>, std::allocator<std::pair<char* const, int> > >::operator= (this=0x8098d1c, __x=...) at /usr/include/c++/4.6/bits/stl_tree.h:945 
#5 0x0804a6bc in std::map<char*, int, std::less<char*>, std::allocator<std::pair<char* const, int> > >::operator= (this=0x8098d1c, __x=...) 
at /usr/include/c++/4.6/bits/stl_map.h:255 
#6 0x080493d3 in MyProg::classify (trainData=..., testsData=...) at my_prog.cpp:78 
#7 0x08049c46 in main() at my_prog.cpp:193 

我已標記在該鏈接的帖子中確切的錯誤點。有人能指出這個錯誤的起源嗎?

ps。它與分配器有什麼關係?加上我不想打擾分配器,除非在這裏是絕對必要的。

編輯:這裏是代碼(從上面的鏈接複製) 注意; <--標誌着錯誤點

InnerMap inmap; 
vector<InnerMap> vec_inmap; 
vec_inmap.resize (8); 
int vec_inmap_sz = 8; 
vec_inmap.insert (vec_inmap.end(), 8, inmap); 
vector<InnerMap>::iterator vec_inmap_it = vec_inmap.begin(); 
InnerMap::iterator inmap_it; 

MiddlMap mdmap, curr_mdmap; 
vector<MiddlMap> vec_mdmap; 
vec_mdmap.resize (8); 
int vec_mdmap_sz = 8; 
vec_mdmap.insert (vec_mdmap.end(), 8, mdmap); 
vector<MiddlMap>::iterator vec_mdmap_it = vec_mdmap.begin(); 
MiddlMap::iterator mdmap_it; 

OuterMap otmap; 
OuterMap::iterator otmap_it; 

即我的商店和inmap (Q.是它的是,這些拷貝是通過引用?)在相應的載體中,然後(空)複製來自拾取這些後來的通過各自的矢量迭代器獲得矢量,然後相應地填充地圖。這裏是如何:

for (i = 0; i != trainSize; i++) { 
... 
if (curr_key_otmap != int_key) { 
    otmap[int_key] = *vec_mdmap_it; 
    vec_mdmap_it++; 
    mdmap_count++; 
    if (mdmap_count == vec_mdmap_sz) { 
     vec_mdmap_sz += 8; 
     vec_mdmap.resize (vec_mdmap_sz); 
     vec_mdmap.insert (vec_mdmap.end(), 8, mdmap); 
    } 
    curr_key_otmap = int_key; 
    curr_mdmap = otmap[curr_key_otmap]; 
} 

mdmap_it = curr_mdmap.find (int_val); 
if (mdmap_it == curr_mdmap.end()) { 
    curr_mdmap[int_val] = *vec_inmap_it;  <-- 
    curr_mdmap[int_val][char_str] = 1; 

    vec_inmap_it++; 
    inmap_count++; 

    if (inmap_count == vec_inmap_sz) { 
     vec_inmap_sz += 8; 
     vec_inmap.resize (vec_inmap_sz); 
     vec_inmap.insert (vec_inmap.end(), 8, inmap); 
    } 
} else { 
    inmap_it = (*mdmap_it).second.find (char_str); 
    if (inmap_it == (*mdmap_it).second.end()) { 
     (*mdmap_it).second[char_str] = 1; 
    } else { 
     (*mdmap_it).second[char_str] += 1; 
    } 
} 
... 
} //for ends 
+0

這可能有助於查看使用此代碼的代碼段。 – jia103

+0

@ jia103提供了代碼 –

回答

4

laune完全正確:在調用resizeinsert後,您的迭代器失效並且可能不再使用。

除了從勞瑞懶懶你不需要在傳喚resize因爲resize增加了在需要時對容器的末日,因爲許多元素之後插入使用矢量的insert功能元素的答案。所以如果你寫

vec_mdmap_sz += 8; 
vec_mdmap.resize (vec_mdmap_sz); 
vec_mdmap.insert (vec_mdmap.end(), 8, mdmap); 

前兩行添加額外的8個元素,最後一行再次插入8個元素。所以你的容器大小增加了16個。您可以使用

vec_mdmap_sz += 8; 
vec_mdmap.resize (vec_mdmap_sz, mdmap); 

,而不是通過8.增加你的容器,但作爲被默認初始化(默認構造函數),你只需拖放參數傳遞給resize功能resize添加默認初始化元素的容器(如果參數類型不提供默認構造函數,那麼調用resize只有大小參數將不會編譯)。

作爲另一個提示您應該使用的迭代器前綴增量操作:不是編寫的

vec_mdmap_it++; 

只使用

++vec_mdmap_it; 

後綴迭代器拷貝迭代器的當前狀態,遞增迭代器並返回舊狀態。所以後綴操作符必須執行復制操作。前綴運算符只是增加迭代器並返回對自身的引用;所以不需要複製操作,所以前綴操作符更快。

+0

好點,+1。非常過度工程,使用矢量簡單明瞭,不需要調整大小和所有... – laune

+0

sleepy42:良好的分析和見解..謝謝你@laune爲你的投入。 加+我得到了解決在另一個鏈接:http://stackoverflow.com/questions/21781811/c-filling-map-of-maps-via-map-instance-allocation-from-a-vector-of-maps –

2

在該代碼中,你不斷遞增

vec_inmap_it++; 

當你重新分配矢量

vec_inmap.resize (vec_inmap_sz); 
從那裏獲得了前

。不要這樣做 - 迭代器可能取決於某個容器的當前位置,並且在重新分配後不再有效。

如果您只是使用索引並通過索引訪問向量,則一切都應該沒問題。