2013-04-15 12 views

Odpowiedz

16

Powyższy kod spowoduje problemy.

Pierwsza instancja jest nazywana statycznym przydzielaniem i definicją ciągów. W przypadku normalnych zmiennych, takich jak int itp., Oraz typów danych nie będących ciągami, taka deklaracja przydzieliłaby dane na stosie. W przypadku łańcuchów inicjowanych za pomocą literałów łańcuchowych (tj .: "stack"), jest on przydzielany w części pamięci przeznaczonej tylko do odczytu.

Sam łańcuch nie powinien być modyfikowany, ponieważ będzie przechowywany w pamięci tylko do odczytu. Sam wskaźnik można zmienić, aby wskazywał nową lokalizację.

tj:

char strGlobal[10] = "Global"; 

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

Aby być bezpiecznym, należy faktycznie przeznaczyć jako wskaźnik do danych const, czyli:

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

Drugi znany jest jako dynamicznej alokacji, która przydziela pamięć na sterty, a nie stosu. Ciąg może być modyfikowany bez kłopotów. W pewnym momencie musisz zwolnić dynamicznie przydzieloną pamięć za pomocą polecenia free().

Istnieje trzeci sposób przydzielania ciągu, który jest statyczną alokacją na stosie. Pozwala to modyfikować zawartość tablicy, która trzyma ciąg znaków, i jest statycznie przydzielana.

char str[] = "Stack"; 

Podsumowując:

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) 

Należy również przeczytać na jaki sposób dane są segmentowane do zastosowań w nowoczesnych systemach operacyjnych. To naprawdę zwiększy zrozumienie tego, jak budowany jest twój kod.

Odniesienia


  1. segmentu danych, do których dostęp 15.04.2013, <http://en.wikipedia.org/wiki/Data_segment>
  2. kod segmentu, do których dostęp 15.04.2013, <http://en.wikipedia.org/wiki/Code_segment>
+2

Mam to, dziękuję. – VishalDevgire

+1

Dodałbym również wariant: 'char str [] =" Stack "' ... –

+0

@ValeriAtamaniouk I byłbyś poprawny. Usprawni. Dzięki za przypomnienie. – DevNull

2

W pierwszym przypadku wskaźnik wskazuje na const char*, który jest przydzielany w pamięci tylko do odczytu.
W drugim przypadku dynamicznie przydzielana jest pamięć, a następnie skopiować ciąg "Stack" do przydzielonej pamięci.

Musisz ostatecznie zwolnić pamięć od II przy użyciu free.

+0

Co się stanie, jeśli spróbuję napisać do obszaru tylko do odczytu (pierwszy przypadek)? – VishalDevgire

+1

Nie można, ponieważ jest to ciąg znaków "const char *". Twój kompilator uniemożliwi ci to. –

+1

Nie ma za co. Nie jest łatwo zrozumieć w pierwszej kolejności ... –

0

Zapomnij o innych odpowiedziach, które mówią coś o przechowywaniu w stosach, ponieważ są niepoprawne. (Oooh teraz te odpowiedzi zostały usunięte ..)

case I: masz wskaźnik str co wskazuje na tylko do odczytu obszaru pamięci (The sekcji .rodata), którego treść jest "Stack".

case II: masz wskaźnik str co wskazuje na dynamicznie przydzielonego regionu (w stosie), którego treść jest "Stack", który jest modyfikowalny i zostanie uwolniony przez invocking free(str) po użyciu go.

Powiązane problemy