我今天晚上几个小时一直在玩下面的代码,我只是在摸着它。
我一直在"无效的写入大小8"和"无效读取大小8和#34;当使用函数从stdin填充数组时。
任何帮助都会受到赞赏......我知道Stack Overflow上有很多这些错误,但大多数都是独特的。
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 :(得分:1)
std::cin >> rawScores[k];
studentInfo[j].score += rawScores[k]/scores[k] * weights[k];
从上面的程序j
和k
取决于用户输入,因此它们的值可以超出实际数组的studentInfo
rawScores
索引。
您的程序应该具有逻辑,以便您的程序不会访问数组边界。
您可以监控您的计划
$ valgrind --tool=memcheck --db-attach=yes ./a.out
有关此概念及其使用方法的详细信息,请参阅以下帖子:
答案 1 :(得分:1)
您是否正确分配了rawScores?
您还需要确保projectCount低于rawScores大小
答案 2 :(得分:0)
它会解决你的问题
答案 3 :(得分:0)
数组边界溢出是阴险的。在c ++中,如果你没有损害你关心的事物,你可能永远不会发现你有些过分......除了你的一些价值观可能不太正确。 (这是&#34;错误&#34;是许多病毒攻击的核心 - 利用写得不好的程序,对缓冲区/数组大小做出假设。
让我们说你有类似的东西:
char buffer[50];
char author[] = "My Name";
cout << author;
cin >> buffer;
如果我输入一个20个字符的输入字符串,没有任何伤害,没有犯规。
如果我输入一个55个字符的输入字符串,&#34;我的名字&#34;将被部分覆盖,没有人会注意到,除非我试图重印作者。这可能不会发生,直到后来的许多(很多)陈述。当你看到作者时,也许它看起来像&#34; 1234ame&#34;,你会问&#34;来自哪里?
更糟糕的是,如果我输入一个70个字符的输入字符串,我会删除作者,以及其后的任何内容,可能是内存管理控制块,i / o缓冲区等等,也许就是&# 34;显&#34; (或不)。
现在,我希望您了解为什么数组管理错误可能在它提交很久之后才会显示,如果有的话。 &#34;没有失败&#34;可能并不意味着&#34;正确&#34;,所以你关于&#34;输出的评论没有显示任何超出界限&#34;可能没有你想象的那么安慰。
正如Rupesh先前所说的那样 - 仔细关注你的数组,包括分配和填充。
如果这不是您需要的答案,那么您需要显示数组的定义及其创建方式。