【问题标题】:Valgrind - invalid read and writeValgrind - 无效的读写
【发布时间】:2013-11-30 16:19:50
【问题描述】:

我有一个谜,我没有答案。我用 C++ 编写了一个简单的程序(我应该说我不是专业的 C++ 开发人员)。这里是:

#include <iostream>

int main(){
  const int SIZE = 1000;
  int pool1 [SIZE];
  int pool2 [SIZE];
  int result [SIZE*SIZE];

  //Prepare data
  for(int i = 0; i < SIZE; i++){
    pool1[i] = i + 1;
    pool2[i] = SIZE - i;
  }

  //Run test
  for(int i = 0; i < SIZE; i++){
    for(int j = 0; j < SIZE; j++){
      result[i*SIZE + j] = pool1[i]*pool2[j];
    }
  }

  return 0; 
}

该程序似乎可以工作(我将它用作不同语言的一种基准),但后来我用 valgrind 运行它,它开始抱怨:

==25912== Invalid read of size 4
==25912==    at 0x804864B: main (in /home/renra/Dev/Benchmarks/array_iteration/array_iteration_cpp)
==25912==  Address 0xbee79da0 is on thread 1's stack

==25912== Invalid write of size 4
==25912==    at 0x8048632: main (in /home/renra/Dev/Benchmarks/array_iteration/array_iteration_cpp)
==25912==  Address 0xbeaa9498 is on thread 1's stack

==25912== More than 10000000 total errors detected.  I'm not reporting any more.
==25912== Final error counts will be inaccurate.  Go fix your program!

嗯,不好看。大小 4 可能是指 int 的大小。正如您最初看到的那样,我使用的是 SIZE 1000,因此结果数组的长度为 1,000,000 个整数。所以,我想,它只是溢出了,我需要一个更大的值类型(至少对于迭代器和结果数组)。我使用了 unsigned long long (unsigned long 的最大值为 18,446,744,073,709,551,615,我只需要 1,000,000 - SIZE*SIZE )。但是我仍然收到这些错误消息(即使 sizeof(long long) 为 8,他们仍然说读写大小为 4)。

当我使用较小的 SIZE 时,这些消息也不存在,但无论使用哪种类型,它们似乎都恰好在 SIZE 707 处出现。有人有线索吗?我很好奇:-)。

【问题讨论】:

  • 您应该在调试模式下编译的程序中使用 valgrind 以获得精确的错误行数。
  • 堆栈上的1000000 元素数组是个坏主意,不要那样做。
  • 你们是否有某种经验法则来确定堆栈中仍然有多少数据是好的,什么时候它已经太多了?
  • @Renra - 典型的默认堆栈为几兆字节。我的经验法则是任何100K不要这样做。您可以使用的另一个指标是缓存大小。如果您拥有的对象大于缓存大小(例如 4K),那么与堆相比,您不一定会在堆栈上获得速度优势。

标签: c++ c valgrind


【解决方案1】:

C 和 C++ 都没有明确限制可以在堆栈上使用的数组大小,而且通常也没有内置保护。只是不要将这么大的块分配为自动(范围本地)变量。为此,请在 C 中使用 malloc 或在 C++ 中使用 new

【讨论】:

  • 谢谢。我在堆上分配了结果数组,valgrind 很高兴。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多