2014-11-08 107 views
0

今天晚上我一直在玩下面的代码几个小时,我只是用它抓挠我的脑袋。无效的读取大小8,无效的写入大小8(Valgrind)

当使用函数从标准输入填充数组时,我总是收到“无效的8号大小写”和“大小8的无效读取”。

任何帮助将不胜感激......我知道堆栈溢出有很多这些错误,但其中大多数是唯一的情况。

void RawScore(unsigned int rawScoreCount, unsigned int numStudents, student studentInfo[], 
       unsigned int projectCount, double rawScores[], double scores[], double weights[]) 
{ 
    int id; 

    for (int i = 0; i < rawScoreCount; i++) 
    { 
     std::cin >> id; 

     for (int j = 0; j < numStudents; j++) 
     { 
      if (id == studentInfo[j].id) 
      { 
       for (int k = 0; k < projectCount; k++) 
       { 
        std::cin >> rawScores[k]; 
        studentInfo[j].score += rawScores[k]/scores[k] * weights[k]; 
       } 
      } 
     } 
      std::cin.ignore(10000, '\n'); 
    } 
} 

从MEMCHECK下面的错误是:

==5793== Memcheck, a memory error detector 
==5793== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==5793== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==5793== Command: a.out.app 
==5793== 
==5793== Invalid write of size 8 
==5793== at 0x40E54DB: std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > std::__1::num_get<char, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > >::__do_get_floating_point<double>(std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, unsigned int&, double&) const (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x40E517E: std::__1::num_get<char, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > >::do_get(std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, unsigned int&, double&) const (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x804D0FA: std::__1::basic_istream<char, std::__1::char_traits<char> >::operator>>(double&) (locale:771) 
==5793== by 0x804CECC: RawScore(unsigned int, unsigned int, student*, unsigned int, double*, double*, double*) (input.cpp:44) 
==5793== by 0x804EE6A: main (main.cpp:35) 
==5793== Address 0x445c388 is 0 bytes after a block of size 40 alloc'd 
==5793== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==5793== by 0x40BA709: operator new(unsigned int) (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x804EE26: main (main.cpp:32) 
==5793== 
==5793== Invalid read of size 8 
==5793== at 0x804CED3: RawScore(unsigned int, unsigned int, student*, unsigned int, double*, double*, double*) (input.cpp:49) 
==5793== by 0x804EE6A: main (main.cpp:35) 
==5793== Address 0x445c388 is 0 bytes after a block of size 40 alloc'd 
==5793== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==5793== by 0x40BA709: operator new(unsigned int) (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x804EE26: main (main.cpp:32) 
==5793== 
....... output of program here ...... 
==5793== 
==5793== HEAP SUMMARY: 
==5793==  in use at exit: 0 bytes in 0 blocks 
==5793== total heap usage: 9 allocs, 9 frees, 476 bytes allocated 
==5793== 
==5793== All heap blocks were freed -- no leaks are possible 
==5793== 
==5793== For counts of detected and suppressed errors, rerun with: -v 
==5793== ERROR SUMMARY: 20 errors from 2 contexts (suppressed: 0 from 0) 

我已经缩小的问题,下面两行,在读10个错误的写入和10:

std::cin >> rawScores[k]; 
studentInfo[j].score += rawScores[k]/scores[k] * weights[k]; 

任何有识之士将不胜感激!

+0

PLZ提供main(),输入参数或两者,如果可能的话。 – 2014-11-08 05:18:23

回答

1
std::cin >> rawScores[k]; 
studentInfo[j].score += rawScores[k]/scores[k] * weights[k]; 

从你上面的程序jk取决于用户输入的,因此它们的值可以超越实际阵列的studentInforawScores指数。

你的程序应该有逻辑,以便它的程序不访问数组边界。

您可以监视您的程序

$ valgrind --tool=memcheck --db-attach=yes ./a.out 

有关这一概念,并详细信息,如何使用它,您可以参考下面的帖子:

https://stackoverflow.com/a/22658693/2724703

+0

输出结果没有显示任何内容。我也在VS调试器上运行这个,并且看不到它出界。 – Sterling 2014-11-08 05:37:07

+0

不受限制的访问具有未定义的行为,因此有时它不会立即出现在程序中。但valgrind报告可以证明您的程序无法访问债券。您可以参考上述建议的步骤,并在错误点进行现场调试。你可以在那个时候验证所有变量和源输入状态。 – 2014-11-08 05:42:15

+0

谢谢!你是对的 - 我玩弄了定义/声明并做了这个:double * rawScores = new double [rawScoreCount + 2]; 对我来说C++是相当新的 - 如果有什么东西碰到了界限,我一直习惯于一个很好的崩溃! – Sterling 2014-11-08 06:01:32

1

你分配rawScores正常吗?

你还需要确保projectCount比rawScores大小

0
  1. 检查是否已分配足够的内存数组下[rawScores, 得分,权重,studentInfo]你传递给这个函数之前。
  2. 检查用户输入,应该在数组范围内。

它会切切实实解决您的问题

0

数组边界溢出是阴险。在C++中,如果你不损害你关心的某些东西,你可能永远不会发现你重蹈覆辙......除了你的某些值可能不是很正确。 (这是“错误”在很多病毒攻击的核心 - 以写得不好的节目,使有关缓冲区/数组大小的假设优势

比方说,你有这样的事情:

char buffer[50]; 
    char author[] = "My Name"; 

    cout << author; 
    cin >> buffer; 

如果我输入一个20个字符的输入字符串,没有伤害,没有犯规。

如果我键入一个55个字符的输入字符串,“我的名字”将被部分覆盖,除非我尝试重新转载作者,否则没有人会注意到。直到许多(许多)陈述后面才会发生。当你看到作者,也许它看起来像“1234ame”,你会问“从哪里来的?”

更糟糕的是,如果我输入一个70个字符的输入字符串,我会垃圾作者,和无论它来自什么,可能是内存管理控制块,I/O缓冲区等,也许这将是“明显”(或不)。直到很长时间后,如果有的话,“没有失败”可能并不意味着“正确”,所以你对“输出不显示任何越界”的评论可能并不如你所期望的那样令人欣慰。早些时候 - 仔细注意你的阵列,两个分配一个填充。

如果这不是您需要的答案,那么您需要显示数组的定义以及它们是如何创建的。