2011-07-22 9 views
8

Decidí sobrecargar los operadores nuevos, nuevos [], ... en mis clases para poder registrar el archivo y la línea a la que se llamaban para poder rastrear más fácilmente las asignaciones/fugas de memoria.Nuevos problemas de operador sobrecargado

Ahora los problemas está en mi pila y matrices de clases (y otras clases de contenedores de plantilla que asignar memoria):

Si los uso con una de mis clases que tiene el nuevo, nuevo [], ... operadores sobrecargados funciona bien.

Pero si lo uso con los tipos de datos estándar de C++ (int, float, ...) no puedo asignarlos, ya que ningún nuevo operador sobrecargado coincide con los argumentos del nuevo (__ LINE __, __ FILE __) operador (u otros como colocación nueva).

Ejemplo de código de pila:

// placement new 
T* t=new(__ LINE __ , __ FILE__)(&m_data[i])T; 

Así que estoy de buenas ideas sobre cómo hacer este trabajo. Si reemplazo nuevo (__ LINE __, __ FILE __) con la nueva capacidad de registro de memoria perdida. Una solución es crear una pila separada para los tipos de datos estándar en los que se usa la nueva configuración predeterminada.

¿Hay alguna forma de detectar en tiempo de compilación si un parámetro de plantilla es una estructura, una clase o un tipo incorporado de C++?

¿Cómo manejas cosas como esta? ¿Qué sugieres? Cualquier comentario sobre este diseño (bueno, malo) es obviamente bienvenido (simplemente no publique cosas como "no reinvente la rueda con sus propios contenedores").

+1

¿Ha sobrecargado ' operador nuevo (__ LINE__, __FILE __) 'globalmente y tratado de usar con' int', 'float', etc. – iammilind

+0

Una opción sería reemplazar global 'operator new()' y friends. – sharptooth

+5

Si está buscando la depuración de fugas de memoria, no veo por qué está haciendo el trabajo de algo que ya existe para esto: ¿Valgrind? – Nim

Respuesta

0
struct Int { 
    int i; 
    Int (int _i) : i(_i) {} 
    operator int() const {return i;} 
}; 

#define __LINE_NUMBER__ Int(__LINE__) 

Utilice esta macro en lugar de la resolución número de línea macro y la sobrecarga norma distinguirá Int números de línea de otros int números.

No me puedo imaginar cómo va a funcionar esto en su totalidad. ¿Lo vas a usar como int * x = NEW(int,123); o algo así?

Estoy de acuerdo con los comentaristas, por cierto, es probable que no tenga que seguir por este camino. La sobrecarga new es una especie de arte negro y normalmente debería evitarse.

+0

No creo que entiendas lo que quiero: no hay ningún problema con la macro __LINE__. ¿O quieres decirme algo más? – n3XusSLO

+0

El problema es que '__LINE__' produce un int que interfiere con la resolución de sobrecarga, ¿verdad? Aquí lo envuelvo en una clase para que las sobrecargas sean diferentes. – spraff

0

¿Hay alguna manera de detectar en tiempo de compilación si un parámetro de plantilla es una estructura, clase o un tipo incorporado en C++?

Puede usar boos :: type_traits y boost :: mpl para ello.

Ejemplo:

#include <boost/type_traits.hpp> 
#include <boost/mpl/not.hpp> 
#include <boost/mpl/logical.hpp> 

template <class T> 
typename boost::enable_if<boost::is_class<T>, T>::type 
foo(){cout << "is class " << endl;}; 

template <class T> 
typename boost::enable_if<boost::mpl::not_<boost::is_class<T> >, T>::type 
foo(){cout << "is not class "<< endl;}; 

lista Tipos - http://www.boost.org/doc/libs/1_47_0/libs/type_traits/doc/html/index.html

O puede utilizar impulso :: :: MPL establecido para su conjunto de tipos

+0

Todavía estoy tratando de entender esto: en una clase de plantilla, ¿podría hacer que el compilador elija usar el nuevo predeterminado o el nuevo sobrecargado en tiempo de compilación en función del tipo de parámetro de la plantilla (por lo que si es una estructura o clase, elegiría nuevo sobrecargado, pero si fuera algo más, ¿elegiría el nuevo predeterminado?) – n3XusSLO

1

Tenga en cuenta que la solución actual requiere la adición el código de registro a cadanew(line, file) sobrecarga que tiene. Además, no puede apagarlo fácilmente en compilaciones de lanzamiento a menos que rodee cada una de sus llamadas de registro dentro de #ifndef DEBUG ... #endif.

Aquí es una manera de lograr lo que wnat: En lugar de sobrecargar el operador new para cada una de sus clases, considere la sobrecarga del operador global new utilizando la sintaxis colocación; de esa manera evita interferir con el operador 'normal' new. A continuación, puede #define nuevo y eliminar macros por conveniencia y, lo más importante, puede tener control sobre cuándo se aplica su seguimiento de memoria new/delete y cuando se utiliza la versión estándar.

#ifdef ENABLE_CUSTOM_ALLOC 

// Custom new operator. Do your memory logging here. 
void* operator new (size_t size, char* file, unsigned int line) 
{ 
    void* x = malloc(size); 
    cout << "Allocated " << size << " byte(s) at address " << x 
     << " in " << file << ":" << line << endl; 
    return x; 
} 

// You must override the default delete operator to detect all deallocations 
void operator delete (void* p) 
{ 
    free(p); 
    cout << "Freed memory at address " << p << endl; 
} 

// You also should provide an overload with the same arguments as your 
// placement new. This would be called in case the constructor of the 
// created object would throw. 
void operator delete (void* p, char* file, unsigned int line) 
{ 
    free(p); 
    cout << "Freed memory at address " << p << endl; 
} 

#define new new(__FILE__, __LINE__) 

#endif 


// A test class with constructors and destructor 
class X 
{ 
public: 
    X() { cout << "X::ctor()" << endl; } 
    X(int x) { cout << "X::ctor(" << x << ")" << endl; } 
    ~X() { cout << "X::dtor()" << endl; } 
}; 


int main (int argc, char* argv[]) 
{ 
    X* x3 = new X(); 
    X* x4 = new X(20); 
    delete x3; 
    delete x4; 
} 

debería ver algo como:

Allocated 1 byte(s) at address 00345008 in Alloc.cpp:58 
X::ctor() 
Allocated 1 byte(s) at address 003450B0 in Alloc.cpp:59 
X::ctor(20) 
X::dtor() 
Freed memory at address 00345008 
X::dtor() 
Freed memory at address 003450B0 

trata de sustituir X para int y verás que funciona también. Puede extender esto a la matriz y ubicación también, pero prefiero no hacer la publicación más larga de lo que es.

Pocas últimos punteros al final:
- MSVC tiene esta funcionalidad, ver here
- No es un toturial de hacer memoria de seguimiento de esta manera here bajo la sección 'Rastreo de pérdidas de memoria'

Cuestiones relacionadas