矩阵类的无效写入大小为4(使用valgrind) [英] Invalid write size of 4 with matrix class (using valgrind)

查看:149
本文介绍了矩阵类的无效写入大小为4(使用valgrind)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的矩阵类,可以与opengl一起使用(es 2.0,afaik没有针对该特定版本的opengl的任何内置版本).

I have a simple matrix class I've made for use with opengl (es 2.0, afaik there isn't any built in version for that particular version of opengl).

基本上,它只是一个向量,该向量的大小已调整为在构造函数中包含16个浮点数(我为它具有的=运算符选择了一个仅在16个浮点数数组上的向量),以及一些对opengl的上下文.无论如何,这些便利结构之一将身份矩阵加载到向量中,它是:

It is basically nothing more than a vector which is resized to contain 16 floats in the constructor, (I chose a vector over just a 16 float array for the = operator it had), and some convenience functions that are useful in the context of opengl. Anyway, one of these convenience structures loads the identity matrix into the vector, it is:

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个浮点数,尽管它也是在构造函数中完成的,而且我认为最终并不需要它,但是现在要删除一个可能的错误,以使工作更轻松调试.

is there to make sure that the size is actually 16 floats, although it's also done in the constructor, and I don't believe it will be needed ultimately, but right now to remove one possible bug, to make life easier for debugging.

Valgrind告诉我这个功能,尤其是这一行:

Valgrind is telling me that this function, in particular this line:

matrix[i] = 0.0f;

导致无效的写入大小4,这听起来令人怀疑,就像我以某种方式调用matrix [16] = 0.0f;.但是,我应该只从0到15.不过,有一点需要注意的是,valgrind还表示正在写入的相关内存是由矩阵的析构函数分配的,更具体地说是由向量的析构函数分配的

is causing an invalid write size of 4, which sounds suspiciously like I'm somehow calling matrix[16] = 0.0f;. However, i should only go from 0 to 15. One interesting thing to note though is that valgrind also says that the memory in question that's getting written to, was allocated by the destructor of the matrix, and more specifically, the destructor of the vector.

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&lt;float&gt;::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&lt;float, std::allocator&lt;float&gt; &gt;::_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&lt;float, std::allocator&lt;float&gt; &gt;::~_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&lt;float, std::allocator&lt;float&gt; &gt;::~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,向量对象主要是指向数组在内存中的位置的指针(嗯,还有其他东西,但是我要指出的是我试图做的是向量对象本身(将存储析构函数的位置)在内存中与实际数组的存储位置不连续,此外,为什么析构函数会在需要时声明内存?整个目的是释放对象使用的内存,这是否会造成内存泄漏呢?顺便说一句,矩阵类没有显式的析构函数,因此仅使用隐式的析构函数.

This seems unlikely if it's just some sort of index out of range error, seeing as, afaik, a vector object is primarily a pointer to where the array is in memory (well, there's other stuff too, but the point I'm trying to make is that the vector object itself (where the destructor would be stored), seems unlikely that it would be contiguous in memory with where the actual array is stored. Also, on top of that, why would a destructor claim memory when it's whole point is to free up the memory an object uses, wouldn't that just create a memory leak? By the way, the matrix class doesn't have an explicit destructor, so just the implicit one is used.

最后,我知道valgrind中的先前错误会导致将来的错误,但是唯一的先前错误是无效的读取大小以及在现有库(OpenGL和SDL)内部使用未初始化的变量,因此,我发现极不可能在这种情况发生之前,它们会导致堆损坏.

Finally, I know that previous errors in valgrind can cause future errors, but the only previous errors is invalid read size and use of uninitiated variables inside of existing libraries (OpenGL and SDL), as such, I find it extremely unlikely that they are causing a heap corruption before this happens.

谢谢.

推荐答案

从您发布的Valgrind报告的摘要中可以很明显地看出,您正在访问向量的悬挂存储.

It's pretty clear from the snippet of Valgrind report you posted that you are accessing dangling storage for a vector.

如果一个线程在向量上进行迭代,而另一线程调整了向量的大小,则很容易出现这种访问.例如,这是不安全的:

Such access could easily arise if one thread is iterating over a vector, while another thread has resized it. For example, this is unsafe:

for (vector<float>::iterator it = matrix.begin(); it != matrix.end(); ++it)
  *it = 0;

在另一个线程中:

matrix.resize(32, 0);

如果您有可以改变向量大小的变异子,那么您必须针对所有阅读器序列化它们,例如

If you have mutators that can resize the vector, then you must serialize all readers with respect to them, e.g.

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);

您在回答中所描述的内容:

What you've described in your answer:

1个图形线程在锁之外获取了matrix.end() [这已经是一个问题].
...
6个图形线程锁
7图形线程获取matrix.begin()并开始迭代

1 Graphics thread gets matrix.end() outside of lock [which is already a problem].
...
6 Graphics thread locks
7 Graphics thread gets matrix.begin() and starts iterating

似乎与Valgrind错误报告不一致,因为它会导致访问超出数组末尾,而Valgrind报告访问是在(现在已删除/悬挂的数组)的开始处进行的.

appears to not be consistent with Valgrind error report, because it would have resulted in access past the end of the array, whereas Valgrind reports access at the beginning of the (now deleted/dangling array).

底线:调用begin()end()和迭代必须全部在保护容器的锁内进行;否则,您的程序行为将是不确定的.

Bottom line: calling begin(), end(), and iteration must all happen within a lock that protects the container; otherwise your program behavior will be undefined.

这篇关于矩阵类的无效写入大小为4(使用valgrind)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆