2010-03-09 9 views
10

¿Hay alguna opción de g ++ que pueda detectar una inicialización incorrecta de std :: string con NULL const char *?Evitando la inicialización incorrecta de std :: string con NULL const char * usando g ++

yo estaba en el proceso de convertir algunos campos int en los std :: string, es decir:

struct Foo 
{ 
    int id; 
    Foo() : id(0) {} 
}; 

... convirtió en:

struct Foo 
{ 
    std::string id; 
    Foo() : id(0) {} //oooops! 
}; 

pasé por alto completamente malas 'id' la inicialización con 0 y g ++ no me dio ninguna advertencia. Este error se detectó en el tiempo de ejecución (std :: string constructor arrojó una excepción) pero realmente me gustaría detectar ese tipo de cosas en el tiempo de compilación. ¿Hay alguna manera?

+2

Desafortunadamente, 0 es el único valor que no generará un error para una conversión inválida de int a puntero. Porque, por supuesto, 0 es una constante de puntero nulo, por lo que es convertible a cualquier tipo de puntero. No sé nada de lo que puedas hacer excepto, como dice el visitante, no escribir ese inicializador en primer lugar. –

+0

La solución adecuada habría sido agregar un constructor privado 'std :: string :: string (int);'. Eso sería una mejor coincidencia, y por lo tanto causar un error en tiempo de compilación. – MSalters

+1

No estoy seguro de si lo decía de esta manera, pero en realidad podría funcionar, como una prueba única para detectar cualquier error resultante de esta ronda de cambios de 'int' a' cadena'. Modifique 'std :: basic_string' en los encabezados estándar de g ++, verifique que el nuevo código compila, luego cámbielo rápidamente antes de que nadie lo note. –

Respuesta

5

Creo que en realidad es un comportamiento indefinido y no verificado por el compilador. Tienes suerte de que esta implementación arroje una excepción.

Sin embargo, puede evitar este tipo de problemas especificando que desea defecto o cero-inicialización de una manera tipo agnóstica:

struct Foo 
{ 
    X id; 
    Foo() : id() {} //note empty parenthesis 
}; 
+0

Hm ... ¿entonces estás diciendo que el constructor predeterminado para tipo int asigna 0? – pachanga

+3

Esta sintaxis significa cero inicialización para tipos incorporados. – visitor

+0

¡Gracias por la información! – pachanga

2

Existe la infraestructura en GCC para producir exactamente este tipo de advertencia:

void foo(const char* cstr) __attribute__((nonnull (1))); 

void bar() { 
    foo(0); 
} 

cuando se compila con -Wnonnull (que está implicado por -Wall) produce:

warning: null argument where non-null required (argument 1) 

Por lo tanto, en principio, usted debería ser capaz de modificar el sistema de cabecera relevante (o, mejor para la experimentación, modifique su propio $ HOME/bits/copiar basic_string.h y luego anular el sistema uno con -isystem $HOME) parecida:

basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()) 
    __attribute__((nonnull (1))); 

Sin embargo, esto no ayuda porque (al menos en 4.0.1) -Wnonnull no es compatible con C++ y aparentemente se ignora el atributo. No es obvio por qué esto es así; quizás se sintió que interactuó mal con la sobrecarga o algo así.

+1

En realidad, su 'basic_string' ctor' __attribute __ ((nonnull (1))) 'anterior comprueba que el puntero' this' no es 'NULL'; simplemente cambie a '__attribute __ ((nonnull (2)))' para verificar que '__s' no sea nulo; ver http://gcc.gnu.org/ml/gcc/2006-04/msg00549.html – vladr

7

No puedo pensar en una manera de detectar esto en tiempo de compilación, así que escribió una función de generador de cadenas que adecuadamente se ocupa de punteros nulos:

// FUNCTION :  safe_string(char const* pszS) 
// PARAMATERS : pszS  source string to build a string from (may be NULL or 0-length) 
// DESCRIPTION : Safely builds a string object from a char*, even a NULL pointer 
// RETURNS :  string 

template<class C> 
inline basic_string<C> safe_string(const C* input) 
{ 
    if(!input) 
     return basic_string<C>(); 
    return basic_string<C>(input); 
} 

utilizo esto cada vez que se crea una cadena y existe la posibilidad de que la entrada sea NULL.

Cuestiones relacionadas