矩阵类的写入大小4无效(使用valgrind)
Invalid write size of 4 with matrix class (using valgrind)
我有一个简单的矩阵类,用于opengl(es 2.0,afaik没有任何特定版本的opengl的内置版本(。
它基本上只不过是一个向量,它的大小被调整为在构造函数中包含16个浮点值(我为它的=运算符选择了一个向量而不是16个浮点数组(,以及一些在opengl上下文中有用的便利函数。总之,这些便利结构之一将单位矩阵加载到向量中,它是:
void Matrix::loadIdentity()
{
matrix.resize(16, 0);
for(int i = 0; i < 16; i++)
matrix[i] = 0.0f;
for(int i = 0; i < 4; i++) {
matrix[i * 4 + i] = 1.0f;
}
}
矩阵所在位置:
std::vector<float>
上面写着:
matrix.resize(16, 0);
是为了确保大小实际上是16个浮点,尽管这也是在构造函数中完成的,我认为最终不需要它,但现在要删除一个可能的错误,让调试变得更容易。
Valgrind告诉我这个功能,特别是这行:
matrix[i] = 0.0f;
导致写入大小为4的无效,这听起来很可疑,好像我在以某种方式调用matrix[16]=0.0f;。然而,我应该只从0到15。不过,需要注意的一件有趣的事情是,valgrind还说,被写入的内存是由矩阵的析构函数分配的,更具体地说,是由向量的析构因子分配的。
Address 0x150f8280 is 0 bytes inside a block of size 64 free'd 1: operator delete(void*) in /build/buildd/valgrind-3.6.1/coregrind/m_replacemalloc/vg_replace_malloc.c:387
2: __gnu_cxx::new_allocator<float>::deallocate(float*, unsigned long) in <a href="file:///usr/include/c++/4.5/ext/new_allocator.h:95" >/usr/include/c++/4.5/ext/new_allocator.h:95</a>
3: std::_Vector_base<float, std::allocator<float> >::_M_deallocate(float*, unsigned long) in <a href="file:///usr/include/c++/4.5/bits/stl_vector.h:146" >/usr/include/c++/4.5/bits/stl_vector.h:146</a>
4: std::_Vector_base<float, std::allocator<float> >::~_Vector_base() in <a href="file:///usr/include/c++/4.5/bits/stl_vector.h:132" >/usr/include/c++/4.5/bits/stl_vector.h:132</a>
5: std::vector<float, std::allocator<float> >::~vector() in <a href="file:///usr/include/c++/4.5/bits/stl_vector.h:314" >/usr/include/c++/4.5/bits/stl_vector.h:314</a>
6: Matrix::~Matrix() in <a href="file:///home/leif/MarbleMachine/core/matrix.h:6" >core/matrix.h:6</a>
如果这只是某种索引超出范围的错误,那么这似乎不太可能,因为,afaik,向量对象主要是指向数组在内存中的位置的指针(好吧,还有其他东西,但我想指出的是,向量对象本身(析构函数的存储位置(在内存中似乎不可能与实际数组的存储位置连续。此外,最重要的是,当析构函数的全部目的是释放对象使用的内存时,为什么析构函数会声明内存,这难道不会造成内存泄漏吗?顺便说一句,矩阵类没有显式的析构函数,所以只使用隐式析构函数。
最后,我知道valgrind中以前的错误可能会导致未来的错误,但以前唯一的错误是无效的读取大小和在现有库(OpenGL和SDL(中使用未初始化的变量,因此,我发现在这种情况发生之前,它们极不可能导致堆损坏。
谢谢。
从您发布的Valgrind报告片段中可以清楚地看出,您正在访问向量的悬挂存储。
如果一个线程在向量上迭代,而另一个线程调整了向量的大小,那么这种访问很容易出现。例如,这是不安全的:
for (vector<float>::iterator it = matrix.begin(); it != matrix.end(); ++it)
*it = 0;
而在另一个线程中:
matrix.resize(32, 0);
如果你有可以调整向量大小的突变子,那么你必须序列化所有与它们相关的读取器,例如
pthread_mutex_lock(&matrix_lock);
for (vector<float>::iterator it = matrix.begin(); it != matrix.end(); ++it)
*it = 0;
pthread_mutex_unlock(&matrix_lock);
在另一个线程中:
pthread_mutex_lock(&matrix_lock);
matrix.resize(32, 0);
pthread_mutex_unlock(&matrix_lock);
你在回答中描述的内容:
1图形线程将matrix.end()
置于锁定之外[这已经是一个问题]
…
6图形线程锁
7图形线程获得matrix.begin()
并开始迭代
似乎与Valgrind错误报告不一致,因为这会导致访问超过数组的末尾,而Valgrind报告访问位于(现已删除/悬挂数组(的开始。
一句话:调用begin()
、end()
和迭代都必须发生在保护容器的锁内;否则,您的程序行为将是未定义的。
谢谢你的帮助,我想我终于想通了。事实证明,我没有给你足够的信息来解决这个问题,所以在我给你我找到的解决方案之前,让我给你更多的信息。
该应用程序是一个多线程应用程序,在每个线程中,它都有一个部分在一个对象循环(相同的对象(上迭代,其中包含矩阵。在一种情况下,它是一个物理引擎,另一种情况是渲染对象。我确实在适当的时候锁定了两个线程中的数据,但事实证明,我在锁定之前就得到了迭代器的末尾。
所以我认为正在发生的事情是:
- 图形线程确定了顶点数组的结束迭代器
- 物理线程锁定了数据
- 物理线程通过了,由于冲突,向线程添加了新项目
- 新数组的大小将大于它的容量,因此它的容量将加倍,从而移动所有数据,并使所有迭代器无效。(我知道每当添加数据时,它们总是无效的,但除非数据的位置发生变化,否则没有不良副作用,afaik(
- 物理线程解锁数据
- 图形线程锁定数据
- 图形线程找到了具有正确位置的起始迭代器,但由于for循环将其与项目#1中的迭代器进行了比较,它偏离了数组的末尾,翻转了无效数据(与设置项目的矩阵以进行绘图有关(
谢谢大家的帮助。
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 如何修复此错误:className::className的无效使用
- '{'标记之前的预期类名,然后在预声明时无效使用不完整的类型'class class_name'
- 二进制表达式的操作数无效 - 使用 for 和迭代器
- C++无效使用非静态成员函数?
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- 在 stream_descriptor::async_wait 中无效使用非静态成员函数
- is_trivially_destructible:无效使用不完整的类型"类 Bar2"
- 在C++中出现错误之前,无效使用了不完整的类型和所需的类型说明符
- 在c++std::函数的上下文中无效使用void表达式
- 错误:无效使用非静态成员函数"int test::hotplug_callback(libusb_contex
- 使用 vector.sort() 的非静态成员函数无效使用
- 使用 std::future 的不完整类型无效使用
- 我在C++中无效使用不完整的类型类错误,如何正确包含头文件?
- 无效使用非静态成员函数 c++ 线程 linux
- 无效使用非静态成员函数 int test::funcAB(int, int)
- '在使用安卓 NDK r10e 构建静态库时无效使用'auto'
- 错误:在 C++ 中无效使用非静态成员函数
- 在没有参数列表的情况下无效使用模板名称"节点"
- 特征向量对数无效使用不完整类型的错误