468,554 Members | 1,955 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,554 developers. It's quick & easy.

Debugging a Segmentation Fault in C++ STL code

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::operator() (this=0xbf91985c,
element=0x8ccea30) at MyHandler.cpp:133

Jan 22 '06 #1
7 2773

<si***************@gmail.com> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
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
Jan 22 '06 #2
TB
si***************@gmail.com 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::operator() (this=0xbf91985c,
element=0x8ccea30) at MyHandler.cpp:133
In do_divide::operator() 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
Jan 22 '06 #3
TB
TB sade:
si***************@gmail.com 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::operator() (this=0xbf91985c,
> element=0x8ccea30) at MyHandler.cpp:133


In do_divide::operator() 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
Jan 22 '06 #4
That is indeed my problem:

Expand|Select|Wrap|Line Numbers
  1. std::vector<int> v1(10); // vector of ten zero-initialized integers
  2. std::vector<int> v2;     // *empty* vector of integers
  3.  
  4. std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
  5. write
  6.  
How can I make sure v2 has enough size before calling 'copy'?

Jan 23 '06 #5

si***************@gmail.com wrote:
That is indeed my problem:

Expand|Select|Wrap|Line Numbers
  1.  std::vector<int> v1(10); // vector of ten zero-initialized integers
  2.  std::vector<int> v2;     // *empty* vector of integers
  3.  std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
  4.  write
  5.  

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

Jan 23 '06 #6
si***************@gmail.com wrote:
That is indeed my problem:

Expand|Select|Wrap|Line Numbers
  1.  std::vector<int> v1(10); // vector of ten zero-initialized integers
  2.  std::vector<int> v2;     // *empty* vector of integers
  3.  std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
  4.  write
  5.  

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

Jan 23 '06 #7
TB
si***************@gmail.com sade:
That is indeed my problem:

Expand|Select|Wrap|Line Numbers
  1.  std::vector<int> v1(10); // vector of ten zero-initialized integers
  2.  std::vector<int> v2;     // *empty* vector of integers
  3.  std::copy(v1.begin(), v1.end(), v2.begin());  // ERROR, no place to
  4.  write
  5.  

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
Jan 23 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

16 posts views Thread by laberth | last post: by
3 posts views Thread by I_have_nothing | last post: by
27 posts views Thread by Paminu | last post: by
7 posts views Thread by pycraze | last post: by
3 posts views Thread by madunix | last post: by
6 posts views Thread by DanielJohnson | last post: by
2 posts views Thread by Zach | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.