我有一个模板类定义为:
#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)
,这意味着它没有像我预期的那样为unsigned long
分配和对齐具体的T type I设置“double”?如果我修改了我的缓冲池实现并硬编码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.
答案 0 :(得分:4)
请注意
之间的区别m_buffer = new T[size];
和
m_buffer = new T[size]();
在前一种情况下,数组未初始化,因此您的valgrind错误:
Conditional jump or move depends on uninitialised value
那就是说,根据我的经验,在这种情况下你可以忽略这个特殊的valgrind输出。因为你显然使用某种blas实现,很可能是你的BLAS库中的优化效果,并且不会做坏事。
答案 1 :(得分: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。