大小8的读取无效,大小8的写入无效(Valgrind)
Invalid read of size 8, Invalid write of size 8 (Valgrind)
今晚我已经玩了几个小时下面的代码,我只是在挠头。
当使用函数从stdin填充数组时,我不断得到"大小为8的无效写入"answers"大小为八的无效读取"。
任何帮助都将不胜感激。。。我知道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];
任何见解都将不胜感激!
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
有关这个概念和如何使用它的详细信息,您可以参考以下帖子:
https://stackoverflow.com/a/22658693/2724703
是否正确分配rawScores?
您还需要确保projectCount低于rawScores大小
- 检查是否为数组分配了足够的内存[rawScores,分数,权重,studentInfo]
- 检查用户输入,应在数组的范围内
它将粗暴地解决您的问题
数组边界溢出是阴险的。在c++中,如果你不损坏你关心的东西,你可能永远不会发现你高估了一些东西。。。只是你的一些价值观可能不太正确。(这是许多病毒攻击的核心"错误"——利用编写不当的程序对缓冲区/数组大小进行假设。
假设你有这样的东西:
char buffer[50];
char author[] = "My Name";
cout << author;
cin >> buffer;
如果我键入一个20个字符的输入字符串,没有伤害,没有犯规。
如果我键入一个55个字符的输入字符串,"我的名字"将被部分覆盖,除非我试图转载作者,否则没有人会注意到这一点。这可能要等到许多(许多)声明之后才会发生。当你们看到作者时,也许它看起来像"1234名字",你们会问"这是从哪里来的?
更糟糕的是,如果我键入一个70个字符的输入字符串,我会丢弃author,以及它之后的任何东西,也许是内存管理控制块、I/o缓冲区等,也许这会"引人注目"(或不引人注目)。
现在,我希望您明白为什么阵列管理错误可能在提交很久之后才会显示(如果有的话)。"没有失败"可能并不意味着"正确",所以你关于"输出没有显示任何超出范围的内容"的评论可能不会像你希望的那样令人欣慰。
正如Rupesh之前所说,要仔细注意您的数组,包括分配和填充。
如果这不是您需要的答案,那么您需要显示数组的定义以及它们是如何创建的。
- FFMPEG配置文件级别id大小无效
- 获取无效的字符串大小
- 在 valgrind c++ 上读取大小 8 无效
- Valgrind 大小为 8 且地址 0x5b7e520 的读取无效,在大小为 16 的块内为 0 字节 free'd
- 在 c++ 中使用 getter 作为unordered_map会创建大小为 8 的无效读取
- C++: free(): 无效的下一个大小(快速)
- 瓦尔格林德:构造函数中大小为 1 的无效读取
- free():多次调用后下一个大小(快速)无效
- free() 中的错误:大小无效
- 使用 OpenCL 进行图像卷积中的参数大小无效
- 为什么我得到 realloc() 无效的旧大小
- 将矢量<int>推入矢量<矢量<int>>时,SIGABRT - free():下一个大小无效(快速)
- free(): 无效的下一个大小 (快速): 0x0000000000f45160 ***.
- C 运行时错误:Free():下一个大小无效(快速)
- Realloc():即使使用malloc()分配内存,旧大小也无效
- 声明std ::配对时大小的写入无效
- 矢量调整大小抛出bad_alloc会使原始数据无效
- 如何修复"在大小为 64 的块内读取大小为 8 - 40 字节的无效 free'd"
- 分割故障和无效的大小为4
- glibc 检测到 free() 无效大小(快速)错误