2010-11-02 50 views
8

Trong khi tôi đang làm việc trên một bài tập, tôi đến để biết rằng chúng ta không nên sử dụng bài tập như:Tại sao chúng ta cần strdup()?

char *s="HELLO WORLD"; 

Programs sử dụng cú pháp như vậy có xu hướng hướng tới đâm.

tôi đã cố gắng và đã sử dụng:

int fun(char *temp) 
{ 
    // do sum operation on temp 
    // print temp. 
    } 
    fun("HELLO WORLD"); 

Ngay cả những công trình ở trên (mặc dù đầu ra là trình biên dịch và tiêu chuẩn cụ thể).

Thay vào đó chúng ta nên cố gắng strdup() hoặc sử dụng const char *

Tôi đã thử đọc câu hỏi tương tự khác trên blog, nhưng anh ta lại quan niệm rằng TẠI SAO TRÊN MÃ should not LÀM VIỆC.

Bộ nhớ được cấp phát ?? Và những gì khác biệt const làm cho ??

+1

Gợi ý: 'const char *' có nghĩa là gì trên 'char *' và tại sao việc sử dụng nó ở trên có lợi (ví dụ: cách * có thể truy cập * hoặc * sửa đổi * s1 "gây ra sự cố")? Strdup là gì cho phép một để làm với 'const char *'? –

+0

'char * s =" HELLO WORLD "' là một khởi tạo, không phải là một nhiệm vụ. Dù sao tại sao bạn nghĩ rằng nó là xấu? – qrdl

Trả lời

11

Cho phép làm rõ mọi thứ một chút. Bạn không bao giờ cần cụ thể strdup. Nó chỉ là một hàm phân bổ một bản sao của một char* trên heap. Nó có thể được thực hiện nhiều cách khác nhau bao gồm cả với bộ đệm dựa trên stack. Những gì bạn cần là kết quả, một bản sao có thể thay đổi của một char*.

Lý do mã bạn liệt kê là nguy hiểm là nó truyền đi những gì thực sự là một chuỗi không đổi trong từ chuỗi ký tự thành một vị trí mong đợi một chuỗi có thể thay đổi. Điều này là không may được cho phép trong tiêu chuẩn C nhưng rất nguy hiểm. Việc ghi vào một chuỗi không đổi sẽ tạo ra các kết quả không mong muốn và thường xuyên bị treo. Chức năng strdupsửa lỗi sự cố vì nó tạo bản sao có thể thay đổi được đặt vào một vị trí mong đợi một chuỗi có thể thay đổi.

+0

Vì vậy, nếu tôi không cố sửa đổi chuỗi, (ví dụ, m chỉ in), sau đó, nó là an toàn để sử dụng như vậy mà không có constals – letsc

+0

@smartmuki nó là hợp pháp theo tiêu chuẩn nhưng chỉ cho lý do compat ngược và vẫn còn là một chuyển đổi nguy hiểm.Nếu bạn xác định một chức năng mà không làm thay đổi chuỗi thì tốt nhất là làm điều đúng và khai báo nó là 'const char *'. – JaredPar

+0

Tôi chỉ thử với trình biên dịch gcc và nó hiển thị kết quả mong đợi. Nhưng một trình biên dịch có thể đưa ra một lỗi phân đoạn cho những điều trên không? Và nếu có, thì y ?? :( – letsc

4

Chuỗi ký tự được lưu trữ trong phân đoạn dữ liệu của chương trình. Thao tác con trỏ của họ sẽ sửa đổi chuỗi chữ, có thể dẫn đến ... kết quả lạ nhất. Sử dụng strdup() để sao chép chúng vào không gian được phân bổ theo chồng hoặc ngăn xếp.

+0

Ngay cả const char * s = "hello" phân bổ không gian cho chữ trên ngăn xếp.Và chúng tôi sử dụng cú pháp như vậy để làm việc xung quanh (Ngay cả trong printf (const char * s, VLA). – letsc

+1

@smartmuki: không phân bổ không gian cho chữ trên ngăn xếp, chỉ có con trỏ đến chữ là trên ngăn xếp. – Darron

+0

@Darron Xin lỗi bt ĐIỀU là gì? Nếu tôi lấy nó cho const char * s, thì nếu không gian được phân bổ trên ngăn xếp (và không phải trên heap), thì có thực sự được phân bổ không? (Hoặc thậm chí được phân bổ) – letsc

1

Đây là sự cố trong C. Mặc dù chuỗi ký tự là char * bạn không thể sửa đổi chúng, vì vậy chúng hiệu quả là const char*.

Nếu bạn đang sử dụng gcc, bạn có thể sử dụng -Wwrite-strings để kiểm tra xem bạn có đang sử dụng đúng chuỗi ký tự chuỗi không.

2

Chuỗi ký tự có thể được lưu trữ trong các phần bộ nhớ không có đặc quyền ghi. Cố gắng viết cho họ sẽ gây ra hành vi không xác định. const có nghĩa là trình biên dịch đảm bảo rằng con trỏ không được ghi vào, đảm bảo rằng bạn không gọi hành vi không xác định theo cách này.

0

Đọc câu trả lời của tôi trên (array & string) Difference between Java and C. Nó chứa câu trả lời cho câu hỏi của bạn trong phần về chuỗi.

Bạn cần hiểu rằng có sự khác biệt giữa phân bổ bộ nhớ tĩnh và bộ nhớ và bạn không sử dụng cùng một không gian bộ nhớ.

Các vấn đề liên quan