2010-10-22 7 views
6

Skąd wskaźnik zwracany przez wywołanie ciąg :: c_str() wskazuje na? W poniższym fragmencie kodu pomyślałem, że dam mu błąd segmentacji, ale daje mi poprawne wyniki. Jeśli wskaźnik zwrócony przez ciąg :: c_str() wskazuje na wewnętrzną lokalizację wewnątrz obiektu napisowego, to po wywołaniu funkcji i wywołaniu destruktora obiektu powinienem uzyskać niepoprawny dostęp do pamięci.ciąg :: c_str zapytanie

#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 

Odpowiedz

13

Skąd wskaźnik zwrócony przez wywołanie string::c_str() wskaż?

Wskazuje miejsce w pamięci, w którym znajduje się zakończony znakiem NUT łańcuch zawierający zawartość std::string.

Wskaźnik jest ważny tylko do czasu zmodyfikowania lub zniszczenia std::string. Jest również potencjalnie unieważniany, jeśli ponownie zadzwonisz pod numer c_str() lub data().

Zasadniczo najbezpieczniej jest założyć, że wskaźnik uzyskany z c_str() został unieważniony, gdy następnym razem zrobisz coś na obiekcie std::string.

Powinienem uzyskać niepoprawny dostęp do pamięci.

Nie, otrzymujesz niezdefiniowane zachowanie. Może pojawić się jakiś błąd dostępu do pamięci (na przykład błąd segmentacji), ale Twój program może również sprawiać wrażenie, że działa poprawnie. Może się wydawać, że działa raz podczas uruchamiania programu, ale kończy się niepowodzeniem.

+0

AFAICT, wskaźnik zwrócony przez 'c_str()' jest ważny do następnego wywołania funkcji niestałej. Ponieważ 'c_str()' i 'data()' są obydwoma "stałymi", nie mogą unieważnić wcześniej zwróconych wskaźników. – MSalters

+1

@MSalters: Tak myślałem, ale: "Referencje, wskaźniki i iteratory odnoszące się do elementów sekwencji' basic_string' mogą zostać unieważnione przez następujące zastosowania tego obiektu 'basic_string': ... Wywołanie danych () 'i' c_str() 'funkcje składowe" (C++ 03 21.3/5). Uznalbym, że 'c_str()' zwraca wskaźnik do elementu w łańcuchu, tak że wskaźnik _ może być unieważniony przez inne wywołanie 'c_str()'. Mogę się mylić. –

+0

Myślę, że istniał pomysł, że basic_string może zaimplementować c_str() przez dodanie '\ 0' do jego wewnętrznego bufora i zwrócenie wskaźnika do tego dołączonego bufora. Taka implementacja rzadko przechowuje '\ 0' i nigdy nie przechowuje dwóch kopii.Cytowany tekst pozwala na to - nie jest sprecyzowane, czy 'c_str' zwraca wskaźnik do elementów lub wskaźnik do kopii tych elementów. – MSalters

2

Czego można się spodziewać, aby wydrukować?

#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; 
} 

W trybie zwolnienia na VS 2010, otrzymuję ten wynik:

przydziałów pamięci niekoniecznie wyjątek podczas próby do niego dostęp . Ta wartość niekoniecznie musi zostać ponownie napisana. (Co ciekawe, jeśli zmienię kompilację na tryb debugowania, kompilator zastąpi wartość wartością -572662307).

Co się stanie, gdy spróbujesz uzyskać dostęp, jest niezdefiniowane przez standard. Oznacza to, że kompilator może robić, co się chce, lub nie robić nic. (Albo zawieść swój program lub wysadzić wszechświat ...)

+0

Doskonała ilustracja .... – Tanuj

Powiązane problemy