|
From: Petr P. <the...@gm...> - 2011-11-09 16:06:33
|
Hello, I came upon this weird behaviour, which is probably best described using a sample, so here it is: http://codepad.org/7zSvMHGZ I think this line alone sums it up pretty nicely: "std::copy_backward(data + 2, data + size, data + size + 1);" (data_m was declared as "int data_m[size + 1];") When I compile the code like so: g++ Test.cpp -ggdb3 and then run valgrind with --leak-check=full on it, I get this: http://codepad.org/1fMnYMbn Again, the line "Source and destination overlap in memcpy(0x7ff00038c, 0x7ff000388, 32)" pretty much sums it up. What am I doing wrong if anything? Is this caused by std::copy_backward using memcpy and not memmove? Or is this a problem on valgrinds's side? Or perhaps none of these? :) Best regards Peter. |
|
From: David C. <dcc...@ac...> - 2011-11-09 18:49:17
|
On 11/9/2011 8:06 AM, Petr Pilař wrote: > Hello, > I came upon this weird behaviour, which is probably best described > using a sample, so here it is: http://codepad.org/7zSvMHGZ > I think this line alone sums it up pretty nicely: > "std::copy_backward(data + 2, data + size, data + size + 1);" (data_m > was declared as "int data_m[size + 1];") > > When I compile the code like so: g++ Test.cpp -ggdb3 and then run > valgrind with --leak-check=full on it, I get this: > http://codepad.org/1fMnYMbn > Again, the line "Source and destination overlap in memcpy(0x7ff00038c, > 0x7ff000388, 32)" pretty much sums it up. > > What am I doing wrong if anything? Is this caused by > std::copy_backward using memcpy and not memmove? Or is this a problem > on valgrinds's side? Or perhaps none of these? :) > > Best regards > Peter. According to http://www.cplusplus.com/reference/algorithm/copy_backward/ "If both ranges overlap in such a way that /result/ (which is the past-the-end element in the destination range) points to an element in the range /[first,last)/, the function copy() should be used instead." The third edition of Stroustrup's "The C++ Programming Language": "We use copy() when the sequences do not overlap, or if the end of the output sequence is in the input sequence. We use copy_backward() when the beginning of the output sequence is in the input sequence. In that way, no element is overwritten until it has been copied." Take a look at the equivalent template implementation in the above link. If in fact this is how the function is implemented in <algorithm>, the compiler could optimize it pretty heavily, and decide to use memcpy() to copy multiple elements at a time rather than implement the core of the loop inline copying single elements. Or maybe the g++ implementation of the template uses memcpy() directly. I bet that you would not get an error with copy_backward() if the number of bytes to be copied is less than 32 (e.g. size == 3, or size == 6 for 32-bit integers). The use of memcpy() this way when the sequences have a substantial amount of overlap is probably a g++ or library bug. What happens if you make your own local version of copy_backward() using the above model and use that? What is in the implementation of copy_backward() in <algorithm>? What version of g++ are you using? -- David Chapman dcc...@ac... Chapman Consulting -- San Jose, CA |