¿Por qué no debería tratar de modificarlo?
Porque es un comportamiento indefinido. Presupuesto de C99 N1256 draft6.7.8/32 "Inicialización":
Ejemplo 8: La declaración
char s[] = "abc", t[3] = "abc";
define los objetos "simple" matriz de caracteres s
y t
cuyos elementos se inicializan con literales de cadena de caracteres .
Esta declaración es idéntica a
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
Los contenidos de las matrices son modificables. Por otra parte, la declaración
char *p = "abc";
define p
con el tipo de "puntero a char" y lo inicializa para apuntar a un objeto con el tipo de "matriz de char" con la longitud de 4 cuyos elementos se inicializan con una cadena de caracteres literal . Si se intenta utilizar p
para modificar el contenido de la matriz, el comportamiento no está definido.
¿A dónde van?
GCC 4.8 x86-64 ELF Ubuntu 14.04:
char s[]
: pila
char *s
:
.rodata
sección del fichero objeto
- el mismo segmento en el que la sección
.text
del fichero objeto se vierten, lo que ha leído y permisos Exec , pero no Escribir
Programa:
#include <stdio.h>
int main() {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compilar y descompilar:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
salida contiene:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
Así que la cadena se almacena en la sección .rodata
.
Entonces:
readelf -l a.out
Contiene (simplificado):
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000704 0x0000000000000704 R E 200000
Section to Segment mapping:
Segment Sections...
02 .text .rodata
Esto significa que la secuencia de comandos enlazador predeterminado vertederos tanto .text
y .rodata
en un segmento que se puede ejecutar pero sin modificar (Flags = R E
) . Intentar modificar dicho segmento conduce a una segfault en Linux.
Si hacemos lo mismo para char[]
:
char s[] = "abc";
obtenemos:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
por lo que se almacena en la pila (en relación con %rbp
), y podemos por supuesto modificarlo.
http://stackoverflow.com/questions/ 164194 | http://stackoverflow.com/questions/1704407 –