una sustituir script reemplazar manejo extraer especiales eliminar caracteres caracter cadenas cadena buscar c linux memory memory-address string-literals

sustituir - ¿Por qué las direcciones de memoria de los literales de cadena son tan diferentes de las de otros en Linux?



sed eliminar caracter (5)

Así es como se presenta la memoria de proceso en Linux (de http://www.thegeekstuff.com/2012/03/linux-processes-memory-layout/ ):

La sección .rodata es una subsección protegida contra escritura del bloque de datos globales inicializados . (Una sección que los ejecutables de ELF designan .data es su contraparte de escritura para las escrituras globales inicializadas en valores distintos de cero. Las escrituras globales escritas inicializadas en ceros van al bloque .bss . Por globales aquí me refiero a las variables globales y todas las variables estáticas independientemente de la ubicación).

La imagen debe explicar los valores numéricos de sus direcciones.

Si desea investigar más a fondo, en Linux puede inspeccionar los archivos virtuales / proc / $ pid / maps que describen el diseño de la memoria de los procesos en ejecución. No obtendrá los nombres de sección ELF reservados (comenzando con un punto), pero puede adivinar de qué sección ELF se originó un bloque de memoria mirando sus banderas de protección de memoria. Por ejemplo, corriendo

$ cat /proc/self/maps #cat''s memory map

me da

00400000-0040b000 r-xp 00000000 fc:00 395465 /bin/cat 0060a000-0060b000 r--p 0000a000 fc:00 395465 /bin/cat 0060b000-0060d000 rw-p 0000b000 fc:00 395465 /bin/cat 006e3000-00704000 rw-p 00000000 00:00 0 [heap] 3000000000-3000023000 r-xp 00000000 fc:00 3026487 /lib/x86_64-linux-gnu/ld-2.19.so 3000222000-3000223000 r--p 00022000 fc:00 3026487 /lib/x86_64-linux-gnu/ld-2.19.so 3000223000-3000224000 rw-p 00023000 fc:00 3026487 /lib/x86_64-linux-gnu/ld-2.19.so 3000224000-3000225000 rw-p 00000000 00:00 0 3000400000-30005ba000 r-xp 00000000 fc:00 3026488 /lib/x86_64-linux-gnu/libc-2.19.so 30005ba000-30007ba000 ---p 001ba000 fc:00 3026488 /lib/x86_64-linux-gnu/libc-2.19.so 30007ba000-30007be000 r--p 001ba000 fc:00 3026488 /lib/x86_64-linux-gnu/libc-2.19.so 30007be000-30007c0000 rw-p 001be000 fc:00 3026488 /lib/x86_64-linux-gnu/libc-2.19.so 30007c0000-30007c5000 rw-p 00000000 00:00 0 7f49eda93000-7f49edd79000 r--p 00000000 fc:00 2104890 /usr/lib/locale/locale-archive 7f49edd79000-7f49edd7c000 rw-p 00000000 00:00 0 7f49edda7000-7f49edda9000 rw-p 00000000 00:00 0 7ffdae393000-7ffdae3b5000 rw-p 00000000 00:00 0 [stack] 7ffdae3e6000-7ffdae3e8000 r--p 00000000 00:00 0 [vvar] 7ffdae3e8000-7ffdae3ea000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

El primer bloque r-xp definitivamente vino de .text (código ejecutable), el primer bloque r--p de .rodata y los siguientes bloques rw-- de .bss y .data . (Entre el montón y el bloque de la pila hay bloques cargados desde bibliotecas vinculadas dinámicamente por el vinculador dinámico).

Nota: Para cumplir con el estándar, debe convertir int* para "%p" en (void*) o de lo contrario el comportamiento no está definido.

Noté que los literales de cadena tienen direcciones muy diferentes en la memoria que otras constantes y variables (sistema operativo Linux): tienen muchos ceros a la izquierda (no impresos).

Ejemplo:

const char *h = "Hi"; int i = 1; printf ("%p/n", (void *) h); printf ("%p/n", (void *) &i);

Salida:

0x400634 0x7fffc1ef1a4c

Sé que están almacenados en la parte .rodata del ejecutable. ¿Existe una forma especial en que el SO lo maneje después, de modo que los literales terminen en un área especial de memoria (con ceros a la izquierda)? ¿Hay alguna ventaja de esa ubicación de memoria o hay algo especial al respecto?


Esto se debe a que los literales de cadena tienen una duración de almacenamiento estático . Es decir, vivirán durante todo el programa. Dichas variables pueden almacenarse en una ubicación de memoria especial que no está ni en el llamado montón ni en la pila. De ahí la diferencia en las direcciones.


Recuerde que donde está un puntero es diferente de donde apunta un puntero. Una comparación más realista (manzanas con manzanas) sería

printf ("%p/n", (void *) &h); printf ("%p/n", (void *) &i);

Sospecho que encontrará que h y p tienen direcciones similares. O, otra comparación más realista sería

static int si = 123; int *ip = &si; printf ("%p/n", (void *) h); printf ("%p/n", (void *) ip);

Sospecho que encontrará que h y ip apuntan a una región similar de memoria.


Tenga en cuenta que los literales son variables de solo lectura y, además, existe un concepto de agrupación literal. El grupo literal es una colección de literales únicos del programa, donde las constantes duplicadas se descartan a medida que las referencias se fusionan en una sola.

Hay un grupo literal para cada fuente, y dependiendo de la sofisticación del programa de enlace / enlace, los grupos literales se pueden colocar uno al lado del otro para crear un .rodata.

Tampoco hay garantía de que el grupo literal esté protegido de solo lectura. El lenguaje, aunque los diseños del compilador lo tratan como tal.

Considera mi fragmento de código. podría tener

const char * cp = "hola mundo";
const char * cp1 = "hola mundo";

El buen compilador reconocerá que dentro de ese código fuente, los literales de solo lectura cp, cp1 , apuntan a cadenas idénticas, y hará que cp1 apunte al literal de cp, descartando el segundo.

Un punto mas. El grupo literal puede ser un múltiplo de 256 bytes o un valor diferente. Si los datos del grupo son inferiores a 256 bytes, la holgura se rellenará con ceros hexadecimales.

Los diferentes compiladores siguen estándares de desarrollo comunes, permitiendo que un módulo compilado con C se vincule con un módulo compilado con lenguaje ensamblador u otro lenguaje. Los dos grupos literales se colocan consecutivamente en .rodata.


printf ("%p/n", h); // h is the address of "Hi", which is in the rodata or other segments of the application. printf ("%p/n", &i); // I think "i" is not a global variable, so &i is in the stack of main. The stack address is by convention in the top area of the memory space of the process.