2008-10-29 15 views
10

Tengo un char* p, que apunta a una cadena terminada en \0. ¿Cómo creo un C++ string de forma segura y sin excepciones?create std :: string from char * de forma segura

Aquí es una versión insegura:

string foo() 
{ 
    char *p = get_string(); 

    string str(p); 
    free(p); 
    return str; 
} 

Una solución obvia sería la de tratar la captura incidental - las maneras más fáciles?

Respuesta

25

Puede utilizar shared_ptr de C++11 o Boost:

string 
foo() 
{ 
    shared_ptr<char> p(get_string(), &free); 
    string str(p.get()); 
    return str; 
} 

Este utiliza una característica muy específica de shared_ptr no está disponible en auto_ptr o cualquier otra cosa, a saber, la posibilidad de especificar un Deleter costumbre; en este caso, estoy usando free como el eliminador.

+0

sí, excepto que no se utilizan normalmente Boost, pero puede crear una clase como a mí mismo. Gracias –

+0

Ese es un ejemplo DULCE. – Allbite

1

Yup - desenrollado basado en pila. Moderno diseño de C++ tiene la solución general pero en este caso se puede utilizar

struct Cleanup { 
     void* toFree; 
     Cleanup(void* toFree) : toFree(toFree) {} 
     ~Cleanup() { free(toFree); } 
    private: 
     Cleanup(Cleanup&); 
     void operator=(Cleanup&); 
}; 

Pase lo que pase con su std :: string, libre (toFree) será llamada cuando el objeto de Limpieza sale del ámbito.

1

Bueno, p no apunta a una cadena terminada en 0 si get_string() devuelve NULL; ese es el problema aquí, ya que los constructores std::string que toman un puntero a una cadena C terminada en 0 no pueden tratar con NULL, que es una cadena C tan terminada en 0 como dos docenas de bananas.

Por lo tanto, si get_string() es su propia función, a diferencia de una función de biblioteca, entonces tal vez debería asegurarse de que no puede devolver NULL. Podría, por ejemplo, dejar que devuelva el buscado std::string, ya que sabe que es de su propio estado. De lo contrario, me gustaría hacer esto, utilizando la Cleanup de this answer como ayudante para garantizar que p no puedan derramarse (como se sugiere por Martin York en un comentario):

string foo() 
{ 
    const char* p = get_string(); 
    const Cleanup cleanup(p); 
    const std::string str(p != NULL ? p : ""); 

    return str; 
} 
+0

Aparte del código no compila (mira en L ""). No es una excepción segura. Usted no garantiza que se lanzará p. –

+0

¡Ah! Lo siento, solo desarrollo para dispositivos basados ​​en Windows CE, y solo tenemos cadenas Unicode, por lo que el prefijo 'L' está clavado en mi columna vertebral cuando escribo código. Ese caso ahora está arreglado. –

+0

¡Uf! Ahora esa fuga también se fue. Gracias por mencionarlo. –

0

Utilizamos comúnmente ScopeGuard para estos casos:

string foo() 
{ 
    char *p = get_string(); 
    ScopeGuard sg = MakeGuard(&free, p); 
    string str(p); 
    return str; 
} 
3

¿Puedo preguntarle qué excepción está esperando en su ejemplo?

En muchas plataformas (Linux, AIX), el nuevo o malloc nunca fallará y su aplicación será destruida por el sistema operativo si se queda sin memoria.

ver este enlace: What happens when Linux runs out of memory.

Cuestiones relacionadas