【问题标题】:Understanding Valgrind's output了解 valgrind 的输出
【发布时间】:2012-08-31 19:05:36
【问题描述】:

我正在为大学写一个项目,一切都完成了,通过了所有测试,运行良好,但 valgrind 告诉我:

==8059== Invalid read of size 8
==8059==    at 0x406E4E: RegPoly::getCurrentCoefficient() const (RegPoly.cpp:59)
==8059==    by 0x403368: MyPoly::operator+(MyPoly const&) const (MyPoly.cpp:281)
==8059==    by 0x403A6D: MyPoly::operator+=(MyPoly const&) (MyPoly.cpp:354)
==8059==    by 0x401E20: main (DemoPoly.cpp:50)
==8059==  Address 0x5953f50 is 0 bytes after a block of size 16 alloc'd
==8059==    at 0x4C27297: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8059==    by 0x4060CD: __gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*) (new_allocator.h:92)
==8059==    by 0x405934: std::_Vector_base<double, std::allocator<double> >::_M_allocate(unsigned long) (in /a/fr-05/vol/home/stud/lablabla/CppLab/Ex3/DemoPoly)
==8059==    by 0x407355: double* std::vector<double, std::allocator<double> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > > >(unsigned long, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >) (stl_vector.h:1052)
==8059==    by 0x40700E: std::vector<double, std::allocator<double> >::operator=(std::vector<double, std::allocator<double> > const&) (vector.tcc:167)
==8059==    by 0x406C5D: RegPoly::RegPoly(RegPoly const&) (RegPoly.cpp:19)
==8059==    by 0x4031DB: MyPoly::operator=(MyPoly const&) (MyPoly.cpp:249)
==8059==    by 0x403B58: MyPoly::operator*=(MyPoly const&) (MyPoly.cpp:364)
==8059==    by 0x401DB6: main (DemoPoly.cpp:44)

线条:

44 - p3 *= p2; // both are MyPoly objects

50 - p3 += p1;

我有点理解这意味着我正在尝试从已更改的内存中读取(?)但我不明白为什么。 我可以发布相关代码,只是,我不确定是哪一部分,因为它会使问题变得混乱。我可以贴相关部分,你需要什么就告诉我。

谢谢!

编辑: 代码如下:

MyPoly& MyPoly::operator *=(const MyPoly& rhs)
{
    *this = *this * rhs; // 364
    return *this;
}

===================

case PolyInterface::REG:
{
    RegPoly *tempReg = dynamic_cast<RegPoly*>(rhs.p_PolyBody); // rhs is an interface, hence the dynamic cast
    if (tempReg != NULL)
    {
        p_PolyBody = new RegPoly(*tempReg);  // 249. p_PolyBody is a pointer stored in MyPoly. points to RegPoly object
    }
    break;
}

===================

RegPoly::RegPoly(RegPoly const& other)
{
    gCurrentRank = 0;
    gData = other.gData; // 19. gData is a vector<double>
    _isZeroPoly = other._isZeroPoly;
}

===================

double RegPoly::getCurrentCoefficient() const
{
    return *gDataIterator; // 59. vector<double>::const_iterator
}

===================

newPolyValues.push_back(
                p_PolyBody->getCurrentCoefficient() + rhs.p_PolyBody->getCurrentCoefficient());
// 281.

编辑: 当getCurrentCoefficient() 返回gData[gCurrentRank] 时,我也会得到这个 这意味着它与 gData 本身的位置有关,对吧?

RegPoly:

std::vector<double> gData;
std::vector<double>::iterator gDataIterator;
int gCurrentRank;
bool _isZeroPoly; // Inherited from the interface

【问题讨论】:

  • RegPoly 类有多少个成员变量?
  • 添加在问题的底部。
  • gDataIterator 是 const_iterator 还是迭代器?除非您非常小心,否则我认为您应该摆脱迭代器成员并使用双变量。迭代器指向一个地址。该地址可以指向任何地方,恕不另行通知。
  • 我尝试了 const 和迭代器。我完全删除了迭代器,RegPoly 中根本没有 gDataIterator。我仍然有同样的泄漏
  • 此消息并非完全泄漏。它更像是内存违规,可能会导致分段错误。 valgrind 的报告总是一样吗?

标签: c++ linux memory-leaks valgrind


【解决方案1】:

相信 valgrind,它几乎总是显示存在的问题。

这是您阅读消息的方式:

RegPoly::getCurrentCoefficient() const (RegPoly.cpp:59) 试图从它不应该读取的内存位置读取,因为它不属于您的应用程序(未分配,非堆栈等...)。这个无效地址刚好超出了新操作符分配的空间,在您的 RegPoly 复制构造函数中使用(您可以看到创建该调用的整个回溯)。

如果这还不够帮助,请发布相关代码。

更新:

我没有看到您的复制构造函数复制了gDataIterator(顺便说一句,当您复制时,为什么要将gCurrentRank 初始化为0?)。

【讨论】:

  • 正在调用 gDataIterator = other.gDataIterator;足够的?因为我仍然从 valgrind 得到错误,它会制作迭代器的深层副本吗?另外,我现在更改了 gCurrentRank
  • 这还不够。问题是:另一个迭代器(可能)指向另一个可以随时更改的地址(当插入元素时,擦除)。您必须使用有效地址进行初始化。
  • 这样做 gDataIterator = gData.begin();需要复制 gData 后吗?试过了,还是一样。 (顺便说一句,像这样复制向量 gData = other.gData 可以吗?它会将值复制到 gData 中,对吧?)
  • 是的,因为 gDataIterator 迭代器可以指向属于另一个容器的地址。关于副本,是的(cplusplus.com/reference/stl/vector/operator=)。为什么不只保存双精度值而不是迭代器?
  • 试过了,完全删除了 gDataIterator,还是一样。我认为这与向量 gData 本身有关。
【解决方案2】:

问题在于 RegPoly.cpp:59 而不是 DemoPoly.cpp:50。

据说您已经分配了 16 个字节,但正在尝试读取超出分配的 8 个字节。

看到这个:http://valgrind.org/docs/manual/mc-manual.html#mc-manual.errormsgs

编辑

您可能正在尝试访问无效的迭代器。一个 const 迭代器只是意味着你不能使用这个迭代器来修改容器内的值。

编辑 2

与无效迭代器相关的brief explanation

【讨论】:

  • 这有点疯狂,问题也可能出在他分配空间的位置......
  • 嗯,你能详细说明一下吗?对我来说,很明显读取了内存上的无效位置。我不明白你试图暗示什么是“疯狂的猜测”。
  • 我添加了对 getCurrentCoefficient() 的检查,以确保 gDataIterator 更少(也检查了!=)感谢 gData.end()。还是一样。取消引用 *gDataIterator 是问题所在,有什么想法吗?
猜你喜欢
  • 2011-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 2015-09-23
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 2016-12-31
相关资源
最近更新 更多