5

我有一个模板类定义为:

#include <stdio.h>
#include <queue>

using namespace std;

template<class T>
class tbufferpool {
private:
    const int m_initial;
    const int m_size;
    const int m_total;
    T *m_buffer;
    vector<T*> m_queue;

public:
    // constructor
    tbufferpool(int initial, int size) : m_initial(initial), m_size(size), m_total(initial*size) {
        m_buffer = new T[m_total];
        T* next_buffer = m_buffer;
        for (int i = 0; i < initial; ++i, next_buffer += size) {
            m_queue.push_back(next_buffer);
        }
    }

在构造函数的某个时刻,我会这样做:

m_buffer = new T[size];

这适用于大多数用例,但在一个测试中,我得到了 valgrind 报告的以下内存错误(下面的命令和相关代码段),但测试仍然可以通过。有趣的一点是operator new(unsigned long)它没有像我预期的那样为我设置“双”的具体 T 类型分配和对齐,但是unsigned long?如果我修改我的缓冲池实现和硬代码new double[size],则不会显示此内存错误,但当然我tbufferpool<double>现在只能使用。

谁能建议如何解决这个问题?new T[size]应该是合法的权利吗?因为模板参数是在编译时由预处理器应用的,它为每个使用的模板类型创建一个新类。这会是编译器错误吗?

test_matrix 是一个包含 30 个测试用例的套件。在 valgrind 中只有一个测试会产生如下所示的问题,但该测试仍然通过。我使用变体检查了问题出处的函数调用的所有输入,并使用new T[size]变体将它们与相同的输入一起打印new double[size]。我使用 AraxisMerge 比较它们,它们是相同的。恐怕是与内存对齐有关的问题取决于我是使用模板参数还是具体的双精度类型...?

$ valgrind --show-reachable=yes --dsymutil=yes --track-origins=yes ./test_matrix
  [snip]
  ==3719== Conditional jump or move depends on uninitialised value(s)
  ==3719==    at 0x3BE86C8: mkl_blas_dscal (in /opt/intel/composerxe-2011.4.184/mkl/lib/libmkl_mc3.dylib)
  ==3719==    by 0x432FFFFFFFFFFFFF: ???
  ==3719==  Uninitialised value was created by a heap allocation
  ==3719==    at 0xD62F: malloc (vg_replace_malloc.c:266)
  ==3719==    by 0x97B15C: operator new(unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib)
  ==3719==    by 0x7FFF5FBFE54F: ???
  ==3719==    by 0x10014BDBF: ???
  ==3719==    by 0x7FFF5FBFE58F: ???
  ==3719==    by 0x97B288: operator new[](unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib)
  ==3719==    by 0x7FFF5FBFE58F: ???
  ==3719==    by 0x100013853: tbufferpool<double>::tbufferpool(int, int) (bufferpool.h:30)
  ==3719==    by 0x7003FFFFF: ???
  ==3719==    by 0x100079E7F: ??? (in ./test_matrix)
  ==3719==    by 0x7FFF5FBFE58F: ???
  ==3719==    by 0x10014BE0F: ???
  ==3719== 
  ==3719== Conditional jump or move depends on uninitialised value(s)
  ==3719==    at 0x3BE86CA: mkl_blas_dscal (in /opt/intel/composerxe-2011.4.184/mkl/lib/libmkl_mc3.dylib)
  ==3719==    by 0x432FFFFFFFFFFFFF: ???
  ==3719==  Uninitialised value was created by a heap allocation
  ==3719==    at 0xD62F: malloc (vg_replace_malloc.c:266)
  ==3719==    by 0x97B15C: operator new(unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib)
  ==3719==    by 0x7FFF5FBFE54F: ???
  ==3719==    by 0x10014BDBF: ???
  ==3719==    by 0x7FFF5FBFE58F: ???
  ==3719==    by 0x97B288: operator new[](unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib)
  ==3719==    by 0x7FFF5FBFE58F: ???
  ==3719==    by 0x100013853: tbufferpool<double>::tbufferpool(int, int) (bufferpool.h:30)
  ==3719==    by 0x7003FFFFF: ???
  ==3719==    by 0x100079E7F: ??? (in ./test_matrix)
  ==3719==    by 0x7FFF5FBFE58F: ???
  ==3719==    by 0x10014BE0F: ???
  [snip]

系统详情:

/Users/bravegag/code/fastcode_project/build_debug$ uname -a && g++ --version
Darwin Macintosh-4.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; 
root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64
g++ (GCC) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4

2 回答 2

4

请注意两者的区别

m_buffer = new T[size];

m_buffer = new T[size]();

在前一种情况下,数组未初始化,因此您的 valgrind 错误:

Conditional jump or move depends on uninitialised value

也就是说,根据我的经验,在这种情况下你可以忽略这个特殊的 valgrind 输出。由于您显然使用了某种 blas 实现,因此很可能是 BLAS 库内部优化的效果,不会做坏事。

于 2012-05-04T11:37:46.267 回答
2

您的问题与内存分配本身无关。Valgrind 说您正在使用指向的数组中的未初始化值m_buffer。你可以得到相同的


T value;
// use value

或者


T values[size];
// use values

要解决此问题,您需要在内存分配后使用适当的值初始化缓冲区,例如


m_buffer = new T[size];
std::fill_n(m_buffer, size, T());


m_buffer = new T[size](); // doesn't work in gcc3.x.x

或者只使用 std::vector 代替。

于 2012-05-04T11:38:44.020 回答