Literales de cadena: ¿a dónde van?

6 minutos de lectura

avatar de usuario
Chris Cooper

Estoy interesado en saber dónde se asignan/almacenan los literales de cadena.

Encontré una respuesta intrigante aquí, diciendo:

La definición de una cadena en línea en realidad incrusta los datos en el propio programa y no se puede cambiar (algunos compiladores permiten esto mediante un truco inteligente, no se moleste).

Pero tenía que ver con C ++, sin mencionar que dice que no se moleste.

estoy molestando =D

Entonces, mi pregunta es ¿dónde y cómo se guarda mi literal de cadena? ¿Por qué no debería intentar alterarlo? ¿La implementación varía según la plataforma? ¿Alguien quiere dar más detalles sobre el “truco inteligente”?

avatar de usuario
Samuel Klatchko

Una técnica común es que los literales de cadena se coloquen en la sección “datos de solo lectura” que se asignan al espacio del proceso como de solo lectura (razón por la cual no puede cambiarlo).

Varía según la plataforma. Por ejemplo, es posible que las arquitecturas de chips más simples no admitan segmentos de memoria de solo lectura, por lo que el segmento de datos se podrá escribir.

En lugar de intentar encontrar un truco para hacer que los literales de cadena se puedan cambiar (dependerá en gran medida de su plataforma y podría cambiar con el tiempo), simplemente use matrices:

char foo[] = "...";

El compilador hará los arreglos para que la matriz se inicialice desde el literal y usted puede modificar la matriz.

  • Sin embargo, debe tener cuidado con el desbordamiento del búfer al usar matrices para cadenas mutables: simplemente escriba una cadena más larga que la longitud de la matriz (por ejemplo, foo = "hello" en este caso) puede causar efectos secundarios no deseados… (asumiendo que no está reasignando memoria con new o algo)

    – johnny

    26 de septiembre de 2011 a las 17:52

  • ¿Cuando se usa una cadena de matriz se coloca en la pila o en otro lugar?

    – Suraj Jain

    26 de diciembre de 2016 a las 11:32

  • ¿No podemos usar char *p = "abc"; para hacer cadenas mutables como dice de manera diferente @ChrisCooper

    – ajaysinghnegi

    27 de julio de 2019 a las 16:39

No hay una respuesta para esto. Los estándares de C y C++ simplemente dicen que los literales de cadena tienen una duración de almacenamiento estática, cualquier intento de modificarlos genera un comportamiento indefinido y varios literales de cadena con el mismo contenido pueden o no compartir el mismo almacenamiento.

Según el sistema para el que esté escribiendo y las capacidades del formato de archivo ejecutable que utiliza, pueden almacenarse junto con el código del programa en el segmento de texto, o pueden tener un segmento separado para los datos inicializados.

La determinación de los detalles también variará según la plataforma; lo más probable es que incluya herramientas que puedan decirle dónde lo está colocando. Algunos incluso le darán control sobre detalles como ese, si lo desea (p. ej., gnu ld le permite proporcionar un script para contarlo todo sobre cómo agrupar datos, codificar, etc.)

  • Me parece poco probable que los datos de la cadena se almacenen directamente en el segmento .text. Para literales realmente cortos, pude ver el compilador generando código como movb $65, 8(%esp); movb $66, 9(%esp); movb $0, 10(%esp) para la cuerda "AB"pero la gran mayoría de las veces estará en un segmento sin código, como .data o .rodata o similar (dependiendo de si el objetivo admite o no segmentos de solo lectura).

    – Adam Rosenfield

    02/10/2012 a las 20:00


  • Si los literales de cadena son válidos durante toda la duración del programa, incluso durante la destrucción de objetos estáticos, ¿es válido devolver la referencia constante a un literal de cadena? Por qué este programa muestra un error de tiempo de ejecución ver ideone.com/FTs1Ig

    – Destructor

    21 de noviembre de 2015 a las 14:48

  • @AdamRosenfield: si alguna vez está aburrido, es posible que desee ver (por ejemplo) el formato heredado UNIX a.out (por ejemplo, freebsd.org/cgi/…). Una cosa que debe notar rápidamente es que solo admite un segmento de datos, que siempre se puede escribir. Entonces, si desea literales de cadena de solo lectura, esencialmente el único lugar donde puede go es el segmento de texto (y sí, en ese momento los enlazadores frecuentemente hacían exactamente eso).

    – Jerry Ataúd

    8 de agosto de 2019 a las 17:43


avatar de usuario
grijesh chauhan

FYI, solo respaldando las otras respuestas:

El estandar: ISO/CEI 14882:2003 dice:

2.13. Literales de cadena

  1. […]Un literal de cadena ordinario tiene el tipo “matriz de n const char” y duración del almacenamiento estático (3.7)

  2. Si todos los literales de cadena son distintos (es decir, se almacenan en objetos que no se superponen) está definido por la implementación. El efecto de intentar modificar un literal de cadena no está definido.

  • Me parece poco probable que los datos de la cadena se almacenen directamente en el segmento .text. Para literales realmente cortos, pude ver el compilador generando código como movb $65, 8(%esp); movb $66, 9(%esp); movb $0, 10(%esp) para la cuerda "AB"pero la gran mayoría de las veces estará en un segmento sin código, como .data o .rodata o similar (dependiendo de si el objetivo admite o no segmentos de solo lectura).

    – Adam Rosenfield

    02/10/2012 a las 20:00


  • Si los literales de cadena son válidos durante toda la duración del programa, incluso durante la destrucción de objetos estáticos, ¿es válido devolver la referencia constante a un literal de cadena? Por qué este programa muestra un error de tiempo de ejecución ver ideone.com/FTs1Ig

    – Destructor

    21 de noviembre de 2015 a las 14:48

  • @AdamRosenfield: si alguna vez está aburrido, es posible que desee ver (por ejemplo) el formato heredado UNIX a.out (por ejemplo, freebsd.org/cgi/…). Una cosa que debe notar rápidamente es que solo admite un segmento de datos, que siempre se puede escribir. Entonces, si desea literales de cadena de solo lectura, esencialmente el único lugar donde puede go es el segmento de texto (y sí, en ese momento los enlazadores frecuentemente hacían exactamente eso).

    – Jerry Ataúd

    8 de agosto de 2019 a las 17:43


avatar de usuario
alex budovski

gcc hace un .rodata sección que se asigna “en algún lugar” en el espacio de direcciones y se marca como de solo lectura,

Visual C++ (cl.exe) hace un .rdata sección con el mismo propósito.

Puedes mirar la salida de dumpbin o objdump (en Linux) para ver las secciones de su ejecutable.

P.ej

>dumpbin vec1.exe
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file vec1.exe

File Type: EXECUTABLE IMAGE

  Summary

        4000 .data
        5000 .rdata  <-- here are strings and other read-only stuff.
       14000 .text

  • No veo cómo desmontar la sección rdata con objdump.

    – usuario2284570

    30 de noviembre de 2015 a las 10:26

  • @ user2284570, eso se debe a que esa sección no contiene ensamblaje. Contiene datos.

    – Alex Budovski

    30 de noviembre de 2015 a las 11:21

  • Solo es cuestión de obtener una salida más legible. Quiero decir que me gustaría tener cadenas en línea con el desmontaje en lugar de dirigirme a esas secciones. (ejem ya sabesprintf("some null terminated static string");en vez deprintf(*address);Cª)

    – usuario2284570

    30 de noviembre de 2015 a las 11:23


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad