2013-04-15 26 views

Trả lời

16

Mã ở trên sẽ gây ra sự cố.

Ví dụ đầu tiên được gọi là phân bổ chuỗi tĩnh và định nghĩa. Đối với các biến thông thường như int, v.v ... và các loại dữ liệu không phải chuỗi, một tuyên bố như vậy sẽ phân bổ dữ liệu trên ngăn xếp. Trong trường hợp chuỗi được khởi tạo thông qua các chuỗi ký tự (ví dụ: "stack"), nó được cấp phát trong phần chỉ đọc của bộ nhớ.

Không nên sửa đổi chuỗi vì nó sẽ được lưu trữ trong phần chỉ đọc của bộ nhớ. Con trỏ chính nó có thể được thay đổi để trỏ đến một vị trí mới.

ví dụ:

char strGlobal[10] = "Global"; 

int main(void) { 
    char* str = "Stack"; 
    char* st2 = "NewStack"; 
    str = str2; // OK 
    strcpy(str, str2); // Will crash 
} 

Để an toàn, bạn nên thực sự phân bổ như một con trỏ đến dữ liệu const, ví dụ:

const char* str = "Stack"; // Same effect as char* str, but the compiler 
          // now provides additional warnings against doing something dangerous 

Thứ hai được gọi là phân bổ năng động, cấp phát bộ nhớ trên đống, không phải là ngăn xếp. Chuỗi có thể được sửa đổi mà không gặp rắc rối. Tại một số thời điểm, bạn cần giải phóng bộ nhớ được cấp phát động này thông qua lệnh free().

Có phương tiện phân bổ chuỗi thứ ba, là phân bổ tĩnh trên ngăn xếp. Điều này cho phép bạn sửa đổi nội dung của mảng đang giữ chuỗi, và nó được phân bổ tĩnh.

char str[] = "Stack"; 

Nói tóm lại:

Example:      Allocation Type:  Read/Write: Storage Location: 
================================================================================ 
const char* str = "Stack";  Static    Read-only  Code segment 
char* str = "Stack";   Static    Read-only  Code segment 
char* str = malloc(...);  Dynamic    Read-write  Heap 
char str[] = "Stack";   Static    Read-write  Stack 
char strGlobal[10] = "Global"; Static    Read-write  Data Segment (R/W) 

Bạn cũng nên đọc lên về cách dữ liệu được phân đoạn cho các ứng dụng trong hệ điều hành hiện đại. Nó thực sự sẽ làm tăng sự hiểu biết của bạn về cách mã của bạn đang được xây dựng.

Tài liệu tham khảo


  1. liệu Segment, Accessed 2013/04/15, <http://en.wikipedia.org/wiki/Data_segment>
  2. Mã Segment, Accessed 2013/04/15, <http://en.wikipedia.org/wiki/Code_segment>
+2

Got it, thanks. – VishalDevgire

+1

Tôi cũng sẽ thêm một biến thể: 'char str [] =" Stack "' ... –

+0

@ValeriAtamaniouk Và bạn sẽ chính xác. Sẽ udpate. Cảm ơn vì đã nhắc tôi. – DevNull

2

Trong trường hợp đầu tiên, con trỏ trỏ tới một số const char* được cấp phát trong phần chỉ đọc của bộ nhớ quá trình.
Trong trường hợp thứ hai, bạn đang cấp phát bộ nhớ động và sự kiện sao chép chuỗi "Stack" vào bộ nhớ được cấp phát của bạn.

Cuối cùng, bạn phải giải phóng bộ nhớ từ II bằng cách sử dụng free.

+0

Và điều gì sẽ xảy ra nếu tôi cố gắng viết vào khu vực chỉ đọc (trường hợp đầu tiên)? – VishalDevgire

+1

Bạn không thể, vì nó là 'const char *' - một chuỗi không đổi. Trình biên dịch của bạn sẽ ngăn bạn làm điều này. –

+1

Bạn được chào đón. Nó không phải là dễ dàng để tìm ra ở nơi đầu tiên ... –

0

Hãy quên đi các câu trả lời khác tuyên bố bất cứ điều gì về việc lưu trữ các ngăn xếp bên trong vì chúng không chính xác. (Oooh bây giờ những câu trả lời đã được loại bỏ ..)

case I: bạn có một con trỏ str mà trỏ đến một read-only khu vực bộ nhớ (phần .rodata) mà nội dung là "Stack".

case II: bạn có một con trỏ str trỏ tới một vùng được cấp phát động (trong đống) mà nội dung là "Stack", đó là sửa đổi và sẽ được giải phóng bởi invocking free(str) sau khi sử dụng nó.

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