我有这个功能,我相信它有重叠的记忆。由于我在我将要阅读的地方之前写作,似乎memcpy
将进入未定义的行为
void overlappingMemcpy() {
int* data = new int[20];
iota(data, data + 20, 1);
printIntData(data, 20);
memcpy(data+1, data, 19*sizeof(int));
printIntData(data, 20);
delete[] data;
}
但是当它与Valgrind一起运行时,我看到没有错误,
> valgrind --tool=memcheck ./ValgrindExamples
==81068== Memcheck, a memory error detector
==81068== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==81068== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==81068== Command: ./ValgrindExamples
==81068==
Hello World!
int data for memory at 0x5b210c0of size 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
int data for memory at 0x5b210c0of size 20
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
==81068==
==81068== HEAP SUMMARY:
==81068== in use at exit: 0 bytes in 0 blocks
==81068== total heap usage: 3 allocs, 3 frees, 73,808 bytes allocated
==81068==
==81068== All heap blocks were freed -- no leaks are possible
==81068==
==81068== For counts of detected and suppressed errors, rerun with: -v
==81068== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我正在使用-O0 -g -fno-inlines -std=c++14
进行编译。程序集显示对memcpy的调用,表明编译器没有内联它,所以我完全失去了为什么它没有被触发。完全组装产生上述方法,
128 [1] void overlappingMemcpy() {
0x401320 55 push %rbp
0x401321 <+0x0001> 48 89 e5 mov %rsp,%rbp
0x401324 <+0x0004> 48 83 ec 20 sub $0x20,%rsp
0x401328 <+0x0008> b8 50 00 00 00 mov $0x50,%eax
0x40132d <+0x000d> 89 c7 mov %eax,%edi
129 [1] int* data = new int[20];
0x40132f <+0x000f> e8 dc f9 ff ff callq 0x400d10 <_Znam@plt>
0x401334 <+0x0014> ba 01 00 00 00 mov $0x1,%edx
0x401339 <+0x0019> 48 89 45 f8 mov %rax,-0x8(%rbp)
130 [1] iota(data, data + 20, 1);
0x40133d <+0x001d> 48 8b 7d f8 mov -0x8(%rbp),%rdi
0x401341 <+0x0021> 48 8b 45 f8 mov -0x8(%rbp),%rax
0x401345 <+0x0025> 48 83 c0 50 add $0x50,%rax
0x401349 <+0x0029> 48 89 c6 mov %rax,%rsi
0x40134c <+0x002c> e8 cf 00 00 00 callq 0x401420 <std::iota<int*, int>(int*, int*, int)>
0x401351 <+0x0031> ba 14 00 00 00 mov $0x14,%edx
0x401356 <+0x0036> 89 d6 mov %edx,%esi
131 [1] printIntData(data, 20);
0x401358 <+0x0038> 48 8b 7d f8 mov -0x8(%rbp),%rdi
0x40135c <+0x003c> e8 df fb ff ff callq 0x400f40 <printIntData(int*, unsigned long)>
0x401361 <+0x0041> ba 14 00 00 00 mov $0x14,%edx
0x401366 <+0x0046> 89 d6 mov %edx,%esi
0x401368 <+0x0048> ba 4c 00 00 00 mov $0x4c,%edx
132 [1] memcpy(data+1, data, 19*sizeof(int));
0x40136d <+0x004d> 48 8b 45 f8 mov -0x8(%rbp),%rax
0x401371 <+0x0051> 48 83 c0 04 add $0x4,%rax
0x401375 <+0x0055> 48 8b 7d f8 mov -0x8(%rbp),%rdi
0x401379 <+0x0059> 48 89 7d f0 mov %rdi,-0x10(%rbp)
0x40137d <+0x005d> 48 89 c7 mov %rax,%rdi
0x401380 <+0x0060> 48 8b 45 f0 mov -0x10(%rbp),%rax
0x401384 <+0x0064> 48 89 75 e8 mov %rsi,-0x18(%rbp)
0x401388 <+0x0068> 48 89 c6 mov %rax,%rsi
0x40138b <+0x006b> e8 d0 f9 ff ff callq 0x400d60 <memcpy@plt>
133 [1] printIntData(data, 20);
0x401390 <+0x0070> 48 8b 7d f8 mov -0x8(%rbp),%rdi
0x401394 <+0x0074> 48 8b 75 e8 mov -0x18(%rbp),%rsi
0x401398 <+0x0078> e8 a3 fb ff ff callq 0x400f40 <printIntData(int*, unsigned long)>
134 [1] delete[] data;
0x40139d <+0x007d> 48 8b 45 f8 mov -0x8(%rbp),%rax
0x4013a1 <+0x0081> 48 83 f8 00 cmp $0x0,%rax
0x4013a5 <+0x0085> 48 89 45 e0 mov %rax,-0x20(%rbp)
0x4013a9 <+0x0089> 0f 84 0c 00 00 00 je 0x4013bb <overlappingMemcpy()+155>
0x4013af <+0x008f> 48 8b 45 e0 mov -0x20(%rbp),%rax
0x4013b3 <+0x0093> 48 89 c7 mov %rax,%rdi
0x4013b6 <+0x0096> e8 05 fa ff ff callq 0x400dc0 <_ZdaPv@plt>
135 [1] }
0x4013bb <+0x009b> 48 83 c4 20 add $0x20,%rsp
0x4013bf <+0x009f> 5d pop %rbp
0x4013c0 <+0x00a0> c3 retq
该工具是否应报告此情况?它在文档页面上说它检测到&#34;将重叠的源和目标内存块传递给memcpy()和相关函数。&#34;
修改
感谢评论者,我发现似乎在上面的程序集中调用的优化版本的memcpy被Valgrind重定向到memmove
(至少,这是我所猜测的)。详细的Valgrind运行在下面,
> valgrind -v ./ValgrindExamples
==56912== Memcheck, a memory error detector
==56912== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==56912== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==56912== Command: ./ValgrindExamples
==56912==
--56912-- Valgrind options:
--56912-- -v
--56912-- Contents of /proc/version:
--56912-- Linux version 4.14.7-041407-generic (kernel@gloin) (gcc version 7.2.0 (Ubuntu 7.2.0-8ubuntu3)) #201712171031 SMP Sun Dec 17 15:33:35 UTC 2017
--56912--
--56912-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-avx-avx2-bmi
--56912-- Page sizes: currently 4096, max supported 4096
--56912-- Valgrind library directory: /usr/lib/valgrind
--56912-- Reading syms from /home/charlie/Projects/build-ValgrindExamples-Desktop-Default/ValgrindExamples
--56912-- Reading syms from /lib/x86_64-linux-gnu/ld-2.26.so
--56912-- Considering /lib/x86_64-linux-gnu/ld-2.26.so ..
--56912-- .. CRC mismatch (computed 89c8df08 wanted 47b839f9)
--56912-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.26.so ..
--56912-- .. CRC is valid
--56912-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux
--56912-- Considering /usr/lib/valgrind/memcheck-amd64-linux ..
--56912-- .. CRC mismatch (computed 9fa343a0 wanted dc854ea8)
--56912-- object doesn't have a symbol table
--56912-- object doesn't have a dynamic symbol table
--56912-- Scheduler: using generic scheduler lock implementation.
--56912-- Reading suppressions file: /usr/lib/valgrind/default.supp
==56912== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-56912-by-charlie-on-???
==56912== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-56912-by-charlie-on-???
==56912== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-56912-by-charlie-on-???
==56912==
==56912== TO CONTROL THIS PROCESS USING vgdb (which you probably
==56912== don't want to do, unless you know exactly what you're doing,
==56912== or are doing some strange experiment):
==56912== /usr/lib/valgrind/../../bin/vgdb --pid=56912 ...command...
==56912==
==56912== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==56912== /path/to/gdb ./ValgrindExamples
==56912== and then give GDB the following command
==56912== target remote | /usr/lib/valgrind/../../bin/vgdb --pid=56912
==56912== --pid is optional if only one valgrind process is running
==56912==
--56912-- REDIR: 0x401f860 (ld-linux-x86-64.so.2:strlen) redirected to 0x58060901 (???)
--56912-- REDIR: 0x401f640 (ld-linux-x86-64.so.2:index) redirected to 0x5806091b (???)
--56912-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so
--56912-- Considering /usr/lib/valgrind/vgpreload_core-amd64-linux.so ..
--56912-- .. CRC mismatch (computed f3fb86a7 wanted 0b99f9ab)
--56912-- object doesn't have a symbol table
--56912-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
--56912-- Considering /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so ..
--56912-- .. CRC mismatch (computed 5ffa922b wanted 4228a583)
--56912-- object doesn't have a symbol table
==56912== WARNING: new redirection conflicts with existing -- ignoring it
--56912-- old: 0x0401f860 (strlen ) R-> (0000.0) 0x58060901 ???
--56912-- new: 0x0401f860 (strlen ) R-> (2007.0) 0x04c32db0 strlen
--56912-- REDIR: 0x401d8d0 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c33ee0 (strcmp)
--56912-- REDIR: 0x401fda0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c374f0 (mempcpy)
--56912-- Reading syms from /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24
--56912-- object doesn't have a symbol table
--56912-- Reading syms from /lib/x86_64-linux-gnu/libm-2.26.so
--56912-- Considering /lib/x86_64-linux-gnu/libm-2.26.so ..
--56912-- .. CRC mismatch (computed b616e9a5 wanted 56d31e5b)
--56912-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/libm-2.26.so ..
--56912-- .. CRC is valid
--56912-- Reading syms from /lib/x86_64-linux-gnu/libgcc_s.so.1
--56912-- object doesn't have a symbol table
--56912-- Reading syms from /lib/x86_64-linux-gnu/libc-2.26.so
--56912-- Considering /lib/x86_64-linux-gnu/libc-2.26.so ..
--56912-- .. CRC mismatch (computed b6c34c34 wanted f79829d1)
--56912-- Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.26.so ..
--56912-- .. CRC is valid
--56912-- REDIR: 0x57c3f50 (libc.so.6:memmove) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c3010 (libc.so.6:strncpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c4230 (libc.so.6:strcasecmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2a60 (libc.so.6:strcat) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c3040 (libc.so.6:rindex) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c5bb0 (libc.so.6:rawmemchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c40c0 (libc.so.6:mempcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c3ee0 (libc.so.6:bcmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2fd0 (libc.so.6:strncmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2ad0 (libc.so.6:strcmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c4020 (libc.so.6:memset) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57e1f10 (libc.so.6:wcschr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2f70 (libc.so.6:strnlen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2b40 (libc.so.6:strcspn) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c4280 (libc.so.6:strncasecmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2b10 (libc.so.6:strcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c43c0 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c3070 (libc.so.6:strpbrk) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2a90 (libc.so.6:index) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c2f40 (libc.so.6:strlen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57ce510 (libc.so.6:memrchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c42d0 (libc.so.6:strcasecmp_l) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c3eb0 (libc.so.6:memchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57e2cc0 (libc.so.6:wcslen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c3350 (libc.so.6:strspn) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c4200 (libc.so.6:stpncpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c41d0 (libc.so.6:stpcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c5be0 (libc.so.6:strchrnul) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x57c4320 (libc.so.6:strncasecmp_l) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--56912-- REDIR: 0x58ad6f0 (libc.so.6:__strrchr_avx2) redirected to 0x4c32730 (rindex)
--56912-- REDIR: 0x57bdeb0 (libc.so.6:malloc) redirected to 0x4c2faa0 (malloc)
--56912-- REDIR: 0x58ad8c0 (libc.so.6:__strlen_avx2) redirected to 0x4c32cf0 (strlen)
--56912-- REDIR: 0x58a9ed0 (libc.so.6:__memcmp_avx2_movbe) redirected to 0x4c35e00 (bcmp)
--56912-- REDIR: 0x58890b0 (libc.so.6:__strcmp_ssse3) redirected to 0x4c33da0 (strcmp)
Hello World!
--56912-- REDIR: 0x4ecc500 (libstdc++.so.6:operator new[](unsigned long)) redirected to 0x4c30830 (operator new[](unsigned long))
--56912-- REDIR: 0x58adde0 (libc.so.6:__mempcpy_avx_unaligned_erms) redirected to 0x4c37130 (mempcpy)
int data for memory at 0x5b210c0of size 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
--56912-- REDIR: 0x58ade00 (libc.so.6:__memcpy_avx_unaligned_erms) redirected to 0x4c366e0 (memmove)
int data for memory at 0x5b210c0of size 20
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
--56912-- REDIR: 0x4eca3b0 (libstdc++.so.6:operator delete[](void*)) redirected to 0x4c316d0 (operator delete[](void*))
--56912-- REDIR: 0x57be3e0 (libc.so.6:free) redirected to 0x4c30cd0 (free)
==56912==
==56912== HEAP SUMMARY:
==56912== in use at exit: 0 bytes in 0 blocks
==56912== total heap usage: 3 allocs, 3 frees, 73,808 bytes allocated
==56912==
==56912== All heap blocks were freed -- no leaks are possible
==56912==
==56912== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==56912== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
所以后续问题:选择致电__memcpy_avx_unaligned_erms
的是什么,我在集会中没有看到它。由于REDIR与memcpy被调用时的对齐,在我看来好像Valgrind已经找到了我在组件中看不到的东西:$