this is related to this question i have asked here : c++ : filling map of maps via map instance allocation from a vector of maps and is unresolved...
The code is all provided there .. the error message (updated here with the first important part of the error that I forgot to report there) is :
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
I have marked the point of exact error in that linked post. Could someone point out about the origin of this error.
ps. how is it related to allocators? plus I dont want to bother about allocators unless it is absolutely necessary here.
Edit: here is the code (copied from the link above)
Note; <--
marks the point of error
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;
i.e. I store (empty) copies of inmap
and mdmap
(Q. is it that these copies are by reference ?) in the respective vectors, and then pick up these later from the vectors through the respective vector iterators, and then fill the maps accordingly. Here is how:
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
laune is completly right: your iterator is invalidated after a call to resize
or insert
and may not be used anymore.
Besides the answer from laune You do not need to insert elements using the insert
function of the vector after having called resize
because resize
adds as many elements as needed at the end of the container. So if You write
vec_mdmap_sz += 8;
vec_mdmap.resize (vec_mdmap_sz);
vec_mdmap.insert (vec_mdmap.end(), 8, mdmap);
the first two lines add additional 8 elements and the last line again inserts 8 elements again. So your container size increased by 16 at all. You can use
vec_mdmap_sz += 8;
vec_mdmap.resize (vec_mdmap_sz, mdmap);
instead to increase your container by 8. But as mdmap
is default initialized (with the default constructor) You can just drop the mdmap
argument to the resize
function as resize
adds default initialized elements to the container (if the parameter type does not provide a default constructor a call to resize
with only a size argument will not compile).
As an other hint You should use the prefix increment operator on iterators: instead of writing
vec_mdmap_it++;
just use
++vec_mdmap_it;
The postfix iterator copies the current state of the iterator, increments the iterator and returns the old state. So the postfix operator has to perform a copy operation. The prefix operator just increases the iterator and returns a reference to itself; so no copy operation is needed and so the prefix operator is faster.
In that code, you keep incrementing
vec_inmap_it++;
while you reallocate the vector
vec_inmap.resize (vec_inmap_sz);
from where it was obtained up front. Don't do that - iterators may depend on the current location of some container and are not valid any more after reallocation.
If you simply use an index and access the vector by indexing, all should be fine.
User contributions licensed under CC BY-SA 3.0