Debugging a Segmentation Fault in C++ STL code

Discussion in 'C++' started by silverburgh.meryl@gmail.com, Jan 22, 2006.

  1. Guest

    Hi,

    I have a C++ problem which uses STL containers and algorithm and it has
    a segmentation fault under some condition.

    Here is a back trace from gdb. Is it possible to tell what is wrong
    from the trace? I know which method is crashing (MyHandler.cpp:133),
    but I don't know why.

    Thanks for any help.

    #0 0x008173a3 in memmove () from /lib/libc.so.6
    #1 0x05d6eace in std::__copy<true,
    std::random_access_iterator_tag>::copy<A*> (__first=0xf762b070,
    __last=0x10, __result=0x0) at stl_algobase.h:300
    #2 0x05d6eafb in std::__copy_aux<A**, A**> (__first=0x89d4f90,
    __last=0x89d4fa0, __result=0x0) at stl_algobase.h:317
    #3 0x05d6eb43 in std::__copy_normal<true,
    true>::copy_n<__gnu_cxx::__normal_iterator<A**, std::vector<A*,
    std::allocator<A*> > >, __gnu_cxx::__normal_iterator<A**,
    std::vector<A*, std::allocator<A*> > > > (__first={_M_current =
    0x89d4f90}, __last={_M_current = 0x89d4fa0}, __result={_M_current =
    0x0}) at stl_algobase.h:354
    #4 0x05d6eb89 in std::copy<__gnu_cxx::__normal_iterator<A**,
    std::vector<A*, std::allocator<A*> > >,
    __gnu_cxx::__normal_iterator<A**, std::vector<A*, std::allocator<A*> >
    > > (__first={_M_current = 0x89d4f90}, __last={_M_current = 0x89d4fa0}, __result={_M_current = 0x0}) at stl_algobase.h:387

    #5 0x05d6fa9d in do_divide::eek:perator() (this=0xbf91985c,
    element=0x8ccea30) at MyHandler.cpp:133
     
    , Jan 22, 2006
    #1
    1. Advertising

  2. Mike Wahler Guest

    <> wrote in message
    news:...
    > Hi,
    >
    > I have a C++ problem which uses STL containers and algorithm and it has
    > a segmentation fault under some condition.
    >
    > Here is a back trace from gdb. Is it possible to tell what is wrong
    > from the trace? I know which method is crashing (MyHandler.cpp:133),
    > but I don't know why.


    Without seeing your code, we can only guess. Try to assemble
    a small, compilable example that still produces the undesired
    behavior and post it here.

    Having said that, I'll go ahead and take a guess:

    > #0 0x008173a3 in memmove () from /lib/libc.so.6
    > #1 0x05d6eace in std::__copy<true,
    > std::random_access_iterator_tag>::copy<A*> (__first=0xf762b070,
    > __last=0x10, __result=0x0) at stl_algobase.h:300
    > #2 0x05d6eafb in std::__copy_aux<A**, A**> (__first=0x89d4f90,
    > __last=0x89d4fa0, __result=0x0) at stl_algobase.h:317


    The diagnostic text you've posted refers to 'std::copy()'.
    Note that this function copies data from one storage location to
    another, *but does not allocate any storage, you must do this
    yourself*. E.g.:

    std::vector<int> v1(10); // vector of ten zero-initialized integers
    std::vector<int> v2; // *empty* vector of integers

    std::copy(v1.begin(), v1.end(), v2.begin()); // ERROR, no place to write

    If this is indeed your problem, look up 'insert_iterator',
    'back_insert_iterator', 'back_inserter', etc. These constructs
    will create storage for 'copy' to write to. Alternatively, look
    at vector::resize(), which will add (or subtract) the necessary number
    of elements to make the vector of the indicated size. (If it adds
    elements, they will be default-initialized).

    But again, this is only my best guess given the limited
    information you provided.

    -Mike
     
    Mike Wahler, Jan 22, 2006
    #2
    1. Advertising

  3. TB Guest

    sade:
    > Hi,
    >
    > I have a C++ problem which uses STL containers and algorithm and it has
    > a segmentation fault under some condition.
    >
    > Here is a back trace from gdb. Is it possible to tell what is wrong
    > from the trace? I know which method is crashing (MyHandler.cpp:133),
    > but I don't know why.
    >
    > Thanks for any help.
    >


    Let me reorder the error messages a bit:

    > #5 0x05d6fa9d in do_divide::eek:perator() (this=0xbf91985c,
    > element=0x8ccea30) at MyHandler.cpp:133


    In do_divide::eek:perator() you're apparently using std::copy().

    > #4 0x05d6eb89 in std::copy<__gnu_cxx::__normal_iterator<A**,
    > std::vector<A*, std::allocator<A*> > >,
    > __gnu_cxx::__normal_iterator<A**, std::vector<A*, std::allocator<A*>
    > > >

    > (__first={_M_current = 0x89d4f90}, __last={_M_current = 0x89d4fa0},
    > __result={_M_current = 0x0}) at stl_algobase.h:387


    The quasi-prototype for std::copy() is:
    OutputIterator copy(InputIterator __first, InputIterator __last,
    OutputIterator __result)

    Now, look at what value '__result' has in your error message:
    __last={_M_current = 0x0}

    I'd guess you're passing an invalid iterator (containing a null pointer
    in this case) to std::copy() which further down in memmove() causes
    your segfault.

    > #0 0x008173a3 in memmove () from /lib/libc.so.6
    > #1 0x05d6eace in std::__copy<true,
    > std::random_access_iterator_tag>::copy<A*> (__first=0xf762b070,
    > __last=0x10, __result=0x0) at stl_algobase.h:300
    > #2 0x05d6eafb in std::__copy_aux<A**, A**> (__first=0x89d4f90,
    > __last=0x89d4fa0, __result=0x0) at stl_algobase.h:317
    > #3 0x05d6eb43 in std::__copy_normal<true,
    > true>::copy_n<__gnu_cxx::__normal_iterator<A**, std::vector<A*,
    > std::allocator<A*> > >, __gnu_cxx::__normal_iterator<A**,
    > std::vector<A*, std::allocator<A*> > > > (__first={_M_current =
    > 0x89d4f90}, __last={_M_current = 0x89d4fa0}, __result={_M_current =
    > 0x0}) at stl_algobase.h:354
    >


    Just watch that nasty bug propagate down the call stack.

    --
    TB @ SWEDEN
     
    TB, Jan 22, 2006
    #3
  4. TB Guest

    TB sade:
    > sade:
    >> Hi,
    >>
    >> I have a C++ problem which uses STL containers and algorithm and it has
    >> a segmentation fault under some condition.
    >>
    >> Here is a back trace from gdb. Is it possible to tell what is wrong
    >> from the trace? I know which method is crashing (MyHandler.cpp:133),
    >> but I don't know why.
    >>
    >> Thanks for any help.
    >>

    >
    > Let me reorder the error messages a bit:
    >
    > > #5 0x05d6fa9d in do_divide::eek:perator() (this=0xbf91985c,
    > > element=0x8ccea30) at MyHandler.cpp:133

    >
    > In do_divide::eek:perator() you're apparently using std::copy().
    >
    > > #4 0x05d6eb89 in std::copy<__gnu_cxx::__normal_iterator<A**,
    > > std::vector<A*, std::allocator<A*> > >,
    > > __gnu_cxx::__normal_iterator<A**, std::vector<A*, std::allocator<A*>
    > > > >

    > > (__first={_M_current = 0x89d4f90}, __last={_M_current = 0x89d4fa0},
    > > __result={_M_current = 0x0}) at stl_algobase.h:387

    >
    > The quasi-prototype for std::copy() is:
    > OutputIterator copy(InputIterator __first, InputIterator __last,
    > OutputIterator __result)
    >
    > Now, look at what value '__result' has in your error message:
    > __last={_M_current = 0x0}


    It should of course read

    __result={_M_current = 0x0}

    not

    __last={_M_current = 0x0}

    --
    TB @ SWEDEN
     
    TB, Jan 22, 2006
    #4
  5. Guest

    That is indeed my problem:

    Code:
    std::vector<int> v1(10); // vector of ten zero-initialized integers
    std::vector<int> v2;     // *empty* vector of integers
    
    std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
    write
    
    How can I make sure v2 has enough size before calling 'copy'?
     
    , Jan 23, 2006
    #5
  6. Gavin Deane Guest

    wrote:
    > That is indeed my problem:
    >
    >
    Code:
    > std::vector<int> v1(10); // vector of ten zero-initialized integers
    > std::vector<int> v2;     // *empty* vector of integers
    >
    > std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
    > write
    > 
    >
    > How can I make sure v2 has enough size before calling 'copy'?


    Create it that big to start with

    std::vector<int> v2(10);

    or create it then call resize

    std::vector<int> v2;
    v2.resize(10);

    Another option which has v2 grow as required (instead of setting it to
    the right size to start with) is to pass a back insert iterator for v2
    to std::copy.

    Gavin Deane
     
    Gavin Deane, Jan 23, 2006
    #6
  7. wrote:
    > That is indeed my problem:
    >
    >
    Code:
    > std::vector<int> v1(10); // vector of ten zero-initialized integers
    > std::vector<int> v2;     // *empty* vector of integers
    >
    > std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
    > write
    > 
    >
    > How can I make sure v2 has enough size before calling 'copy'?


    Mike Wahler already anticipated your question and answered it. Here's
    his response again:

    > If this is indeed your problem, look up 'insert_iterator',
    > 'back_insert_iterator', 'back_inserter', etc. These constructs
    > will create storage for 'copy' to write to. Alternatively, look
    > at vector::resize(), which will add (or subtract) the necessary number
    > of elements to make the vector of the indicated size. (If it adds
    > elements, they will be default-initialized).


    Best regards,

    Tom
     
    Thomas Tutone, Jan 23, 2006
    #7
  8. TB Guest

    sade:
    > That is indeed my problem:
    >
    >
    Code:
    > std::vector<int> v1(10); // vector of ten zero-initialized integers
    > std::vector<int> v2;     // *empty* vector of integers
    > 
    > std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
    > write
    > 
    >
    > How can I make sure v2 has enough size before calling 'copy'?
    >


    One pratical way to solve this is to use a back inserter:

    #include <iterator>
    std::copy(v1.begin(), v1.end(), std::back_inserter(v2));

    The inserter will call push_back() on the container for
    each new element, thus relieving you of making sure
    the container is preallocated to a certain size.

    Another way is to resize the vector to the same size
    of the source container:

    v2.resize(v1.size());

    --
    TB @ SWEDEN
     
    TB, Jan 23, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. mblome
    Replies:
    3
    Views:
    4,721
    Old Wolf
    Jun 14, 2005
  2. Steve
    Replies:
    2
    Views:
    517
    Andre Kostur
    Nov 6, 2007
  3. Replies:
    2
    Views:
    597
  4. Giacecco
    Replies:
    0
    Views:
    144
    Giacecco
    Sep 25, 2006
  5. nrolland
    Replies:
    0
    Views:
    126
    nrolland
    Oct 28, 2006
Loading...

Share This Page