You are not logged in.
This sample code
#include <string>
#include <iostream>
int main ()
{
std::string str("this is a test std::string.");
str.replace(9, 5, "n example of");
std::cout << str << std::endl;
str.replace(8, 2, "a short");
std::cout << str << std::endl;
return 0;
}
run it with
$ g++ sample.cpp && valgrind ./a.out
then valgrind says
==8297== Source and destination overlap in memcpy(0x592f0e7, 0x592f0e2, 24)
==8297== at 0x4C27B46: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8297== by 0x4ED27A8: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6.0.16)
==8297== by 0x4ED284B: std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) (in /usr/lib/libstdc++.so.6.0.16)
==8297== by 0x4ED40DD: std::string::replace(unsigned long, unsigned long, char const*, unsigned long) (in /usr/lib/libstdc++.so.6.0.16)
==8297== by 0x400B7D: main
Have I done anything bad?
Following is my system and g++ info:
$ uname -a
Linux 2.6.39-ARCH #1 SMP PREEMPT Sat Jul 9 14:57:41 CEST 2011 x86_64 Intel(R) Core(TM) i5 CPU M 460 @ 2.53GHz GenuineIntel GNU/Linux
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /build/src/gcc-4.6.1/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --enable-gnu-unique-object --enable-linker-build-id --with-ppl --enable-cloog-backend=isl --enable-lto --enable-gold --enable-ld=default --enable-plugin --with-plugin-ld=ld.gold --disable-multilib --disable-libstdcxx-pch --enable-checking=release
Thread model: posix
gcc version 4.6.1 (GCC)
Offline
No, you haven't done anything wrong. This is a bogus warning triggered by the standard library. Just ignore it.
Last edited by lunar (2011-07-24 08:52:55)
Offline
That actually looks like a pretty terrible bug in libstdc++.
EDIT: If you change the code to this:
#include <string>
#include <iostream>
namespace std
{
template class basic_string<char>;
}
int main ()
{
std::string str("this is a test std::string.");
str.replace(9, 5, "n example of");
std::cout << str << std::endl;
str.replace(8, 2, "a short");
std::cout << str << std::endl;
return 0;
}
then g++ will instantiate std::string in your code instead of libstdc++. Then running "g++ -Wall -g foo.cpp && valgrind ./a.out" gives
==16000== Source and destination overlap in memcpy(0x592f0e7, 0x592f0e2, 24)
==16000== at 0x4C27B46: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16000== by 0x403D29: std::char_traits<char>::move(char*, char const*, unsigned long) (char_traits.h:269)
==16000== by 0x4040AD: std::string::_M_move(char*, char const*, unsigned long) (basic_string.h:363)
==16000== by 0x404443: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (basic_string.tcc:495)
==16000== by 0x406735: std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) (basic_string.tcc:686)
==16000== by 0x40601C: std::string::replace(unsigned long, unsigned long, char const*, unsigned long) (basic_string.tcc:425)
==16000== by 0x4061F5: std::string::replace(unsigned long, unsigned long, char const*) (basic_string.h:1470)
==16000== by 0x403B60: main (foo.cpp:14)
==16000==
But line 269 of /usr/include/c++/4.6.1/bits/char_traits.h says
{ return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); }
and the disassembly clearly shows a call to memmove():
(gdb) disas
Dump of assembler code for function std::char_traits<char>::move(std::char_traits<char>::char_type*, std::char_traits<char>::char_type const*, std::size_t):
0x0000000000403cff <+0>: push %rbp
0x0000000000403d00 <+1>: mov %rsp,%rbp
0x0000000000403d03 <+4>: sub $0x20,%rsp
0x0000000000403d07 <+8>: mov %rdi,-0x8(%rbp)
0x0000000000403d0b <+12>: mov %rsi,-0x10(%rbp)
0x0000000000403d0f <+16>: mov %rdx,-0x18(%rbp)
0x0000000000403d13 <+20>: mov -0x18(%rbp),%rdx
0x0000000000403d17 <+24>: mov -0x10(%rbp),%rcx
0x0000000000403d1b <+28>: mov -0x8(%rbp),%rax
0x0000000000403d1f <+32>: mov %rcx,%rsi
0x0000000000403d22 <+35>: mov %rax,%rdi
=> 0x0000000000403d25 <+38>: callq 0x4037f0 <memmove@plt>
0x0000000000403d2a <+43>: leaveq
0x0000000000403d2b <+44>: retq
End of assembler dump.
So clearly this is a valgrind bug, where it's intercepting calls to memmove() as to memcpy() for some reason. Reproducer:
#include <string.h>
#include <stdio.h>
int
main()
{
char test[] = " This is a test.";
memmove(test, test + 1, 5);
printf("%s\n", test);
return 0;
}
Valgrind complains about the parameters to memcpy() when there obviously isn't a call to it! And, if you change the call to memcpy(), the warning goes away! Valgrind has confused memmove() and memcpy().
EDIT 2: I've reported it here: https://bugs.kde.org/show_bug.cgi?id=278502
Last edited by tavianator (2011-07-25 20:49:42)
Offline