Perché l’errore di segmentazione nel seguente codice?

Ho letto questo su wikipedia

int main(void) { char *s = "hello world"; *s = 'H'; } 

Quando il programma contenente questo codice è compilato, la stringa “ciao mondo” viene posizionata nella sezione del file eseguibile del programma contrassegnata come di sola lettura; quando caricato, il sistema operativo lo colloca con altre stringhe e dati costanti in un segmento di memoria di sola lettura. Quando viene eseguita, una variabile, s, è impostata per puntare alla posizione della stringa e viene fatto un tentativo di scrivere un carattere H attraverso la variabile nella memoria, causando un errore di segmentazione **

non so perché la stringa è posta in segmento di sola lettura. Per favore qualcuno potrebbe spiegarlo.

I valori letterali delle stringhe sono memorizzati nella memoria di sola lettura, è così che funziona. Il tuo codice utilizza un puntatore inizializzato per puntare alla memoria dove è memorizzato un valore letterale di stringa, e quindi non puoi modificare validamente quella memoria.

Per ottenere una stringa in memoria modificabile, fai questo:

 char s[] = "hello world"; 

allora stai bene, dal momento che stai usando la stringa costante per inizializzare un array non costante.

C’è una grande differenza tra:

 char * s = "Hello world"; 

e

 char s[] = "Hello world"; 

Nel primo caso, s è un puntatore a qualcosa che non puoi cambiare. È memorizzato nella memoria di sola lettura (in genere, nella sezione del codice dell’applicazione).

In quest’ultimo caso, si assegna un array in memoria di lettura / scrittura (in genere RAM semplice), che è ansible modificare.

  • Quando lo fai: char *s = "hello world"; allora s è un puntatore che punta a una memoria che si trova nella parte del codice , quindi non puoi cambiarla.

  • Quando lo fai: char s[] = "Hello World"; allora s è un array di caratteri che sono in pila , quindi puoi cambiarlo.

Se non vuoi che la stringa venga cambiata durante il programma, è meglio fare: char const *s = ....; . Quindi, quando si tenta di cambiare la stringa, il programma non si bloccherà con l’errore di segmentazione , si verificherà un errore del compilatore (che è molto meglio).

prima ho una buona comprensione dei puntatori, ti darò una breve demo:

Per prima cosa analizziamo il codice riga per riga. Iniziamo dalla main in poi

char * s = “Some_string”;

prima di tutto, stai dichiarando un puntatore a una variabile char, ora * s è un indirizzo in memoria e C ti kickerà se proverai a cambiare il suo valore di memoria, che è illegale, quindi devi dichiarare un array di caratteri, quindi assegnare s al suo indirizzo, quindi cambia s.

Spero che tu lo capisca. Per ulteriori riferimenti e comprensione dettagliata, consultare KN King: C programming A Modern Approach

Per la definizione della lingua, i valori letterali delle stringhe devono essere memorizzati in modo tale che la loro durata si estenda per tutta la durata del programma e che siano visibili sull’intero programma.

Esattamente ciò che questo significa in termini di dove viene memorizzata la stringa è fino all’implementazione ; la definizione della lingua non impone che i valori letterali delle stringhe siano memorizzati nella memoria di sola lettura, e non tutte le implementazioni lo fanno. Dice solo che il tentativo di modificare il contenuto di una stringa letterale si traduce in un comportamento indefinito, il che significa che l’implementazione è libera di fare ciò che vuole.