2010-10-22 10 views
6

¿Dónde apunta el puntero al llamar a string :: c_str()? En el siguiente fragmento de código, pensé que obtendría un error de segmentación, pero me da el resultado correcto. Si el puntero devuelto por string :: c_str() apunta a una ubicación interna dentro del objeto de cadena, cuando la función retorna y se invoca el destructor de objetos, debería obtener un acceso de memoria no válido.cadena :: consulta c_str

#include <iostream> 
#include <string> 
using namespace std; 

const char* func() 
{ 
    string str("test"); 
    return str.c_str(); 
} 

int main() 
{ 
    const char* p = func(); 
    cout << p << endl; 
    return 0; 
} 

Output: test 
Compiler: g++ 4.3.3 
Platform: ubuntu 2.6.28-19 

Respuesta

13

dónde viene el puntero devuelto llamando a punto de string::c_str()?

Apunta a un lugar en la memoria donde se encuentra una cadena terminada en nulo que contiene el contenido de la std::string.

El puntero solo es válido hasta que el std::string se modifique o destruya. También se puede invalidar si llama nuevamente al c_str() o data().

Básicamente, su apuesta más segura es suponer que el puntero obtenido de c_str() se invalida la próxima vez que haga algo al objeto std::string.

Debería obtener un acceso no válido a la memoria.

No, obtiene un comportamiento indefinido. Es posible que obtenga un error de acceso a la memoria de algún tipo (como un error de segmentación), pero su programa también podría seguir funcionando correctamente. Puede parecer que funciona una vez que ejecuta su programa pero falla al siguiente.

+0

AFAICT, el puntero devuelto por 'c_str()' es válido hasta la siguiente llamada a una función no const. Como 'c_str()' y 'data()' son ambos 'const' themelves, no pueden invalidar los punteros devueltos previamente. – MSalters

+1

@MSalters: lo pensé muy bien, pero: "Referencias, punteros e iteradores que se refieren a los elementos de una secuencia' basic_string' pueden ser invalidados por los siguientes usos de ese objeto 'basic_string': ... Calling' data () 'y' c_str() 'funciones miembro" (C++ 03 21.3/5). Considero que 'c_str()' devuelve un puntero a un elemento en la cadena para que el apuntador _debe ser invalidado por otra llamada a 'c_str()'. Yo podría estar equivocado en eso. –

+0

Creo que la idea era que basic_string podría implementar c_str() añadiendo un '\ 0' a su búfer interno y devolviendo un puntero al búfer adjunto. Tal implementación raramente almacenaría un '\ 0', y nunca almacenaría dos copias.El texto que cites permite esto: no se especifica si 'c_str' devuelve un puntero a los elementos o un puntero a una copia de esos elementos. – MSalters

2

¿Qué esperas que imprima?

#include <iostream> 
#include <string> 

int main() 
{ 
    int* test = new int[20]; 
    test[15] = 5; 
    std::cout << test[15] << "\n"; 
    delete[] test; 
    std::cout << test[15] << "\n"; 
    return 0; 
} 

En el modo de disparo en VS 2010, me sale el siguiente resultado:

memoria

desasignada no necesariamente una excepción cuando intenta acceder a él . El valor tampoco necesariamente se vuelve a escribir. (Curiosamente, si cambio la compilación al modo de depuración, el compilador sobrescribe el valor con -572662307).

Lo que sucede cuando intentas acceder a él no está definido por la norma. Eso significa que el compilador puede hacer lo que le da la gana, o decide no hacer nada. (O bloquear su programa, o explotar el universo ...)

+0

Excelente ilustración .... – Tanuj

Cuestiones relacionadas