2010-09-03 6 views

risposta

7

Lo standard stabilisce che le stringhe letterali siano definite const. Non puoi cambiarlo

Il compilatore inserisce il letterale in una sezione di memoria di sola lettura. È possibile emettere il gruppo e osservare questo. Se si utilizza GCC, viene eseguito tramite il flag -s. Inserirà la stringa in una sezione .rodata.

+0

e se scrivo char arr [10] = "nyks"; arr [2] = 'p'; mostrerà nuovamente l'errore seg? – Kraken

+1

@ spiacente, no. Questo va bene, dato che stai allocando una matrice (modificabile) nello stack. Come ho notato sopra, puoi lasciare le dimensioni in modo che C lo calcoli. –

+1

No, in C, i valori letterali stringa non hanno un tipo 'const'. Tuttavia, è un comportamento indefinito scrivere su di loro. –

15

È un comportamento indefinito provare a sovrascrivere una stringa letterale. C99 §6.4.5/6:

Se il programma tenta di modificare tale un array, il comportamento è unde Definito.

Questo è rideterminato nell'appendice J.2 (comportamento non definito).

Se invece fai:

char p[] = "nyks"; 

è possibile allocare e inizializzare un (stack) array di caratteri automatico. In tal caso, è perfettamente corretto modificare gli elementi.

+0

+ non è più possibile avere dichiarazioni letterali stringa non costanti. GCC emetterà un grande avvertimento rosso. –

+0

+1 per riferimento alla specifica – linuxuser27

0

Le stringhe non sono modificabili ... La capacità di scrivere char *p="nyks"; è in realtà un buco sistema tipo a C.

+0

In che modo si tratta di un buco nel sistema di tipi? – alternative

+0

Per ragioni storiche, il compilatore è stato autorizzato a eseguire il cast di 'const' in questo caso. Naturalmente, al momento in cui 'const' è stato inventato e hanno notato che una costante di stringa deve essere effettivamente' const char * ', è probabile che sia stato considerato un grosso cambiamento per proibire l'assegnazione a' char * '. – RBerteig

+0

@mathepic Dal punto di vista del C++, almeno. In C++, un carattere letterale è di tipo const char [N]. Una stringa letterale può essere convertita implicitamente in char non const * (qualifica const rimossa senza cast). Questo è un buco di sistema di tipo in C++, ma questo comportamento è stato ereditato da C. Questa è una funzionalità deprecata in C++ e verrà completamente rimossa in C++ 0x. Ecco cosa ha da dire lo standard C in merito a questa domanda: "Se il programma tenta di modificare tale array, il comportamento non è definito." dove "tale array" è un array di caratteri che contiene una stringa letterale. – usta

1

Ciò si traduce in (essenzialmente):

#include<stdio.h> 
const char privatestring[5] = {"nyks"}; 

void main() 
{ 
    char *p = const_cast<char*>(privatestring); 
    p[2]='n';   

    printf("%s",p);   
}   

Il compilatore è permesso inserisci privatestring da qualche parte in cui hai solo accesso in lettura. Fa il const_cast per la retrocompatibilità con i programmi scritti prima che fosse una parola chiave const.

3

Altre risposte dicono il punto di vista dal punto di vista degli standard, ma ecco perché si verifica un arresto anomalo dello.

I compilatori in genere inseriscono letterali di programma, in particolare stringhe, nella memoria di sola lettura. La memoria è contrassegnata in sola lettura dal sistema operativo, quindi qualsiasi tentativo di scrittura su di esso verrà intrappolato e, sulla piattaforma, questo è ciò che indica l'errore di segmentazione; un tentativo di eseguire un'operazione su una memoria che non è consentita. L'altro tipo di arresto anomalo associato a un cattivo utilizzo della memoria è un errore del bus, che in genere indica un accesso non allineato alla memoria o una scrittura a una pagina che non è mappata affatto. Per il codice C, la differenza è quasi interamente accademica (alcune altre implementazioni linguistiche utilizzano questi errori per aiutarli a gestire la memoria).

Si noti che il trapping delle scritture in sola lettura è indipendente dalla semantica ufficiale della lingua. Mentre potresti avere un char* che punta ad esso, non puoi ancora scriverlo. Trattate sempre i valori letterali del programma come se puntassero a memoria costante e non vi sbagliate (che non lo sono per impostazione predefinita a causa della necessità di supportare la compatibilità con programmi meno recenti).

+0

E lo standard (C89) non specifica cosa accade quando si scrive in un letterale precisamente perché non volevano specificare il modo esatto in cui si verifica un arresto anomalo e perché volevano anche consentire ai compilatori di supportare stringhe scrivibili se volevano (ad esempio, tramite un interruttore, gcc ha '-fwritable-stringhe' per fare quel genere di cose, anche se bisognerebbe che fosse davvero solo un'indicazione di un programma malamente rotto se me lo chiedete). –

1

Il valore è un valore letterale stringa che non può essere modificato perché i valori letterali sono memorizzati nella memoria di sola lettura, provare p []. Gli errori di segmentazione generalmente si verificano a causa di un uso errato dei puntatori.

Problemi correlati