He una clase de plantilla definida como:C++ "new T [size]" no funciona?
#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);
}
}
y en algún momento en el constructor que hago:
m_buffer = new T[size];
Esto funciona para la mayoría de los casos de uso, pero en una prueba me sale el siguiente memoria error reportado por valgrind (comando y fragmento relevante a continuación) la prueba todavía es correcta. El bit interesante es operator new(unsigned long)
, lo que significa que no se está asignando y alineando para la configuración concreta tipo T "doble", como esperaba, pero para unsigned long
? Si modifico la implementación de mi grupo de almacenamiento intermedio y el código duro new double[size]
, este error de memoria no se muestra, pero por supuesto ahora solo trabajo con tbufferpool<double>
ahora.
¿Alguien puede aconsejar cómo solucionar esto? el new T[size]
debería ser legal ¿verdad? ya que los parámetros de la plantilla se aplican en tiempo de compilación por el pre-procesador que crea una nueva clase para cada tipo de plantilla utilizada. ¿Sería esto un error del compilador?
Test_matrix es una suite que contiene 30 casos de prueba. Solo una prueba produce el problema que se muestra a continuación en valgrind, sin embargo, la prueba pasa. Comprobé todas las entradas a la llamada de función donde se origina el problema usando la variante new T[size]
y las imprimí junto a las mismas entradas usando la variante new double[size]
. Los comparo usando AraxisMerge y son idénticos. Me temo que un problema relacionado con la alineación de la memoria es diferente dependiendo de si utilizo el parámetro de plantilla o el tipo doble concreto ...?
$ 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]
detalles del sistema:
/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.
Solo un pensamiento, pero tal vez es porque 'double' es del mismo tamaño que' unsigned long'. – Tibor
Intente aislar el problema (una instanciación de la plantilla 'tbufferpool' con tipo double, elimine la mayor cantidad posible del constructor) y vuelva a publicar el código. Lo más importante es cómo se inicializa 'size'. –
Eso significa que no ha inicializado una parte de esa memoria asignada, pero debería haberlo hecho. ¿Estás inicializando esa memoria asignada? – mfontanini