Valgrind是否显示阵列拷贝错误? 考虑下面的非常简单的C++代码: #include <algorithm> #include <iostream> using namespace std; int main() { int a[7] = {1, 2, 3, 4, 5, 6, 7}; int b[7]; copy(a, a+7, b); for (int i=0; i<8; ++i) cout << b[i] << endl; } #包括 #包括 使用名称空间std; int main() { inta[7]={1,2,3,4,5,6,7}; int b[7]; 副本(a、a+7、b); for(int i=0;i

Valgrind是否显示阵列拷贝错误? 考虑下面的非常简单的C++代码: #include <algorithm> #include <iostream> using namespace std; int main() { int a[7] = {1, 2, 3, 4, 5, 6, 7}; int b[7]; copy(a, a+7, b); for (int i=0; i<8; ++i) cout << b[i] << endl; } #包括 #包括 使用名称空间std; int main() { inta[7]={1,2,3,4,5,6,7}; int b[7]; 副本(a、a+7、b); for(int i=0;i,c++,valgrind,C++,Valgrind,超过数组末尾会导致未定义的行为,这意味着任何事情都可能发生。但是,如果指针未取消引用,则允许进入数组的指针超过数组一次 这是允许的,这样您就可以检查数组的结尾,并在带有迭代器的容器中使用它容器迭代器的函数指向末尾的一个。但这永远不会被取消引用,否则您将处于未定义的行为区域。Valgrind中的memcheck工具不会报告基于堆栈的内存错误(除非超出堆栈顶部的地址空间)。它报告基于堆的内存错误。在堆上分配数组,Valgrind应报告无效读取(不是从复制,而是从结束后的for循环) #包括: Mem

超过数组末尾会导致未定义的行为,这意味着任何事情都可能发生。但是,如果指针未取消引用,则允许进入数组的指针超过数组一次


这是允许的,这样您就可以检查数组的结尾,并在带有迭代器的容器中使用它容器迭代器的函数指向末尾的一个。但这永远不会被取消引用,否则您将处于未定义的行为区域。

Valgrind中的memcheck工具不会报告基于堆栈的内存错误(除非超出堆栈顶部的地址空间)。它报告基于堆的内存错误。在堆上分配数组,Valgrind应报告无效读取(不是从
复制
,而是从结束后的
for
循环)

#包括:

Memcheck是一个内存错误检测器。它可以检测以下内容 C和C++程序中常见的问题。 访问不应访问的内存,例如堆溢出和堆不足 块,溢出堆栈顶部,并在 它被释放了。 使用未定义的值,即未初始化的值,或从其他未定义值派生的值

不正确地释放堆内存,例如双重释放堆块, 或者malloc/new/new[]与free/delete/delete[]的使用不匹配

memcpy和相关函数中重叠的src和dst指针

内存泄漏


a+7
表达式不是错误-这是副本的结束指示符,永远不会访问。副本的执行时间为,但不包括
a+7


然而,
cout我想我明白了。基本上发生的是,任何地方都无法访问*(a+7)。对std::copy的调用最终归结为memmove,再加上Seth在第5.7.5节中发布的内容,我认为我们在这里做得很好:

(gdb) down
#0  std::__copy_aux<int*, int*> (__first=0x7fff5fbffb8c, __last=0x7fff5fbffba8, __result=0x7fff5fbffb70) at stl_algobase.h:313
313                  && __are_same<_ValueTypeI, _ValueTypeO>::__value);
(gdb) n
315       return std::__copy<__simple, _Category>::copy(__first, __last, __result);
(gdb) s
std::__copy<true, std::random_access_iterator_tag>::copy<int> (__first=0x7fff5fbffb8c, __last=0x7fff5fbffba8, __result=0x7fff5fbffb70) at stl_algobase.h:298
298       std::memmove(__result, __first, sizeof(_Tp) * (__last - __first));
(gdb) list
293     {
294       template<typename _Tp>
295         static _Tp*
296         copy(const _Tp* __first, const _Tp* __last, _Tp* __result)
297         { 
298       std::memmove(__result, __first, sizeof(_Tp) * (__last - __first));
299       return __result + (__last - __first);
300     }
301     };
302 
(gdb)关闭
#0 std::uuuuu copy_uaux(uuuuu first=0x7fff5fbffb8c,uuuuuuuu last=0x7fff5fbffba8,uuuuuuuuuu result=0x7fff5fbffb70)在stl\u algobase.h:313
313&&&uuuuu相同::uuu值);
(gdb)n
315返回std::uuu copy::copy(uuu first,uuu last,uuu result);
(gdb)s
std::uuu copy::在stl_algobase.h:298处复制(uuuu first=0x7fff5fbffb8c,uuuuuu last=0x7fff5fbffba8,uuuuuuuu result=0x7fff5fbffb70)
298 std::memmove(uuu result,uu first,sizeof(u Tp)*(uu last-u first));
(gdb)清单
293     {
294模板
295静态*
296份(先施工,后施工,最后施工,结果)
297         { 
298 std::memmove(uuu result,uu first,sizeof(u Tp)*(uu last-u first));
299返回uuu结果+(uuu最后-uu第一);
300     }
301     };
302

它应该报告它吗?我对valgrind不太熟悉,但您可以写入该内存。为什么您要向我们显示GDB输出?为什么您要谈论valgrind,但不显示任何valgrind输出?这是恶作剧吗?看起来您对
a[7]的程序还不够深入
待办事项run@KerrekSB:你可能是那种对毫无戒心的人进行随机恶作剧的人,但坦率地说,我对这种无聊的行为没有耐心。我之所以显示GDB输出,是因为它正在访问1+上一个已知的有效数组地址(即a+6)@fantactic23别无礼。它也不是访问1+最后已知的有效数组地址,它只是存储1的地址,没有访问它,这很好。这是我需要知道的。你能告诉我标准中提到这一点的相应部分吗。我想他说的是
(int i=0;i@SethCarnegie看看OP在你的评论上面所说的。我知道8过了一个终点就被取消引用了,但他在他的问题中说的是a+7。-1,回答错误。当然这是未定义的行为。问题是为什么Valgrind,一个错误检测工具,没有检测到错误。§5.7.5是相关的,我认为:此外,我f表达式P指向数组对象的最后一个元素,表达式(P)+1指向数组对象的最后一个元素,如果表达式Q指向数组对象的最后一个元素,则表达式(Q)-1指向数组对象的最后一个元素。如果指针操作数和结果都指向同一数组对象的元素,或超过数组对象最后一个元素的元素,则求值不应产生溢出;否则,行为未定义。
#include <algorithm>
#include <iostream>
#include <cstring>

int main()
{
  int* a = new int[7];
  int* b = new int[7];
  std::memset(a, 0, sizeof(int) * 7);
  std::memset(b, 0, sizeof(int) * 7);

  std::copy(a, a+7, b);

  for (int i=0; i<8; ++i)
    std::cout << b[i] << std::endl;

  delete[] a;
  delete[] b;
}
(gdb) down
#0  std::__copy_aux<int*, int*> (__first=0x7fff5fbffb8c, __last=0x7fff5fbffba8, __result=0x7fff5fbffb70) at stl_algobase.h:313
313                  && __are_same<_ValueTypeI, _ValueTypeO>::__value);
(gdb) n
315       return std::__copy<__simple, _Category>::copy(__first, __last, __result);
(gdb) s
std::__copy<true, std::random_access_iterator_tag>::copy<int> (__first=0x7fff5fbffb8c, __last=0x7fff5fbffba8, __result=0x7fff5fbffb70) at stl_algobase.h:298
298       std::memmove(__result, __first, sizeof(_Tp) * (__last - __first));
(gdb) list
293     {
294       template<typename _Tp>
295         static _Tp*
296         copy(const _Tp* __first, const _Tp* __last, _Tp* __result)
297         { 
298       std::memmove(__result, __first, sizeof(_Tp) * (__last - __first));
299       return __result + (__last - __first);
300     }
301     };
302