Question

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
Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top