2010-10-22 38 views
6

Trường hợp con trỏ trả về bằng cách gọi chuỗi :: c_str() trỏ tới? Trong đoạn mã sau đây, tôi nghĩ rằng tôi sẽ cung cấp cho một lỗi phân đoạn nhưng nó mang lại cho tôi đầu ra chính xác. Nếu con trỏ được trả về bởi chuỗi :: c_str() trỏ đến một vị trí bên trong bên trong đối tượng chuỗi, thì khi hàm trả về và đối tượng destructor được gọi, tôi sẽ nhận được truy cập bộ nhớ không hợp lệ.chuỗi :: truy vấn 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 

Trả lời

13

đâu con trỏ trở lại bằng cách gọi string::c_str() điểm đến?

Nó trỏ đến một số vị trí trong bộ nhớ trong đó chuỗi có chứa null được chứa nội dung của std::string.

Con trỏ chỉ hợp lệ cho đến khi std::string được sửa đổi hoặc bị hủy. Nó cũng có khả năng bị vô hiệu nếu bạn gọi lại c_str() hoặc data().

Về cơ bản, đặt cược an toàn nhất của bạn là giả định con trỏ thu được từ c_str() không hợp lệ trong lần tiếp theo bạn làm điều gì đó với đối tượng std::string.

Tôi sẽ nhận được quyền truy cập bộ nhớ không hợp lệ.

Không, bạn nhận được hành vi không xác định. Bạn có thể gặp phải lỗi truy cập bộ nhớ của một số loại (như lỗi phân đoạn), nhưng chương trình của bạn cũng có thể xuất hiện để tiếp tục chạy một cách chính xác. Nó có thể xuất hiện để làm việc một thời gian bạn chạy chương trình của bạn nhưng thất bại tiếp theo.

+0

AFAICT, con trỏ được trả về bởi 'c_str()' là hợp lệ cho đến khi cuộc gọi tiếp theo đến một hàm không const. Vì 'c_str()' và 'data()' là cả hai 'const' themelves, chúng có thể không làm mất hiệu lực con trỏ trả về trước đó. – MSalters

+1

@MSalters: Tôi cũng nghĩ như vậy, nhưng: "Tham chiếu, con trỏ và vòng lặp đề cập đến các phần tử của chuỗi' basic_string' có thể bị vô hiệu bởi các sử dụng sau của đối tượng 'basic_string': ... Gọi' dữ liệu () 'và' c_str() 'các hàm thành viên" (C++ 03 21.3/5). Tôi sẽ xem xét 'c_str()' khi trả về một con trỏ tới một phần tử trong chuỗi để con trỏ _could_ bị vô hiệu hóa bởi một lệnh gọi khác đến 'c_str()'. Tôi có thể sai về điều đó. –

+0

Tôi nghĩ rằng ý tưởng có rằng basic_string có thể thực hiện c_str() bằng cách thêm một '\ 0' vào bộ đệm bên trong của nó, và trả về một con trỏ tới bộ đệm được nối thêm đó. Việc triển khai như vậy hiếm khi lưu trữ một '\ 0' và không bao giờ lưu trữ hai bản sao.Văn bản bạn trích dẫn cho phép điều này - nó không được chỉ định cho dù 'c_str' trả về một con trỏ tới các phần tử hoặc một con trỏ tới một bản sao của các phần tử đó. – MSalters

2

Bạn mong đợi điều này để in ra?

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

Trong chế độ phát hành trên VS 2010, tôi nhận được kết quả này:

deallocated bộ nhớ không nhất thiết phải ném một ngoại lệ khi bạn cố gắng truy cập vào nó . Giá trị không nhất thiết phải được viết lại. (Thật thú vị, nếu tôi thay đổi biên dịch sang chế độ gỡ lỗi, trình biên dịch sẽ ghi đè giá trị bằng -572662307).

Điều gì sẽ xảy ra khi bạn cố gắng truy cập vào nó không được xác định theo tiêu chuẩn. Điều đó có nghĩa là trình biên dịch có thể làm bất cứ điều gì nó cảm thấy như làm, hoặc chọn không làm gì cả. (Hoặc phá vỡ chương trình của bạn, hoặc thổi lên vũ trụ ...)

+0

Minh họa tuyệt vời .... – Tanuj