Debugging a Segmentation Fault in C++ STL code

S

silverburgh.meryl

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**,
#5 0x05d6fa9d in do_divide::eek:perator() (this=0xbf91985c,
element=0x8ccea30) at MyHandler.cpp:133
 
M

Mike Wahler

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
 
T

TB

(e-mail address removed) 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**,

> (__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.
 
T

TB

TB sade:
(e-mail address removed) sade:

Let me reorder the error messages a bit:


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


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}
 
S

silverburgh.meryl

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'?
 
G

Gavin Deane

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
 
T

Thomas Tutone

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
 
T

TB

(e-mail address removed) 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());
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top