2010-09-03 15 views

Respuesta

7

El estándar dicta que las cadenas literales se definen const. No puedes cambiarlo

El compilador coloca el literal en una sección de memoria de solo lectura. Puede sacar el ensamblaje y observar esto. Si está utilizando GCC, lo hace a través del indicador -s. Colocará la cadena en una sección de .datata.

+0

y si escribo char arr [10] = "nyks"; arr [2] = 'p'; ¿mostrará seg fault nuevamente? – Kraken

+1

@hopeful, no. Eso está bien, ya que estás asignando una matriz (modificable) en la pila. Como mencioné anteriormente, puede omitir el tamaño para que C lo calcule. –

+1

No, en C, los literales de cadena no tienen el tipo 'const'. Sin embargo, es un comportamiento indefinido escribirles. –

15

Es un comportamiento indefinido intentar sobrescribir una cadena literal. C99 §6.4.5/6:

Si el programa intenta modificar tal una matriz, el comportamiento es indefinido.

Esto se actualiza en el Apéndice J.2 (comportamiento indefinido).

Si en lugar de hacerlo:

char p[] = "nyks"; 

puede asignar e inicializar un (pila) array de caracteres automática. En ese caso, está perfectamente bien modificar elementos.

+0

+ ya no está permitido tener declaraciones literales de cadenas no constantes. GCC emitirá una gran advertencia roja. –

+0

+1 para referencia a la especificación – linuxuser27

0

literales de cadena no son modificables ... La capacidad de escribir char *p="nyks"; es en realidad un agujero sistema de tipos en C.

+0

¿Cómo es esto un agujero del sistema tipo? – alternative

+0

Por razones históricas, al compilador se le permitió descartar silenciosamente 'const' en este caso. Por supuesto, en el momento en que se inventó 'const' y notaron que una constante de cadena debe ser efectivamente' const char * ', probablemente se consideró que era un gran cambio interrumpir la asignación a' char * '. – RBerteig

+0

@mathepic Desde el punto de vista de C++, al menos. En C++, un carácter literal es de tipo const char [N]. Un literal de cadena se puede convertir implícitamente a charla no const * (la calificación const se elimina sin un molde). Este es un agujero de sistema de tipo en C++, pero este comportamiento fue heredado de C. Esta es una característica en desuso en C++, y se eliminará por completo en C++ 0x. Esto es lo que el estándar C tiene que decir al respecto de esta pregunta: "Si el programa intenta modificar dicha matriz, el comportamiento no está definido". donde 'such a array' es una matriz de caracteres que contiene una cadena literal. – usta

1

Eso se traduce en (esencialmente):

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

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

    printf("%s",p);   
}   

se permite que el compilador ponga privatestring en algún lugar donde solo tenga acceso de lectura. Hace el const_cast por compatibilidad con versiones anteriores de programas escritos anteriormente que era una palabra clave const.

3

Otras respuestas dicen que la vista desde la perspectiva de los estándares, pero aquí está por qué se bloquea.

Los compiladores suelen poner literales de programa, especialmente cadenas, en la memoria de solo lectura. La memoria está marcada como de solo lectura por el sistema operativo, por lo que cualquier intento de escribir quedará atrapado y, en su plataforma, esto es lo que indica la falla de segmentación; un intento de hacer una operación en alguna memoria que no está permitida. El otro tipo de bloqueo asociado con el mal uso de memoria es un error de bus, que generalmente indica un acceso a la memoria no alineado o una escritura en una página que no está asignada en absoluto. Para el código C, la diferencia es casi completamente académica (algunas implementaciones en otros idiomas usan estas fallas para ayudarlos a administrar la memoria).

Tenga en cuenta que la captura de escrituras para solo lectura es independiente de la semántica oficial del idioma. Si bien es posible que tengas un char* señalando, aún no puedes escribirlo. Siempre trate los literales del programa como si estuvieran apuntando a la memoria constante y no se equivocará (que no es así por defecto es debido a la necesidad de admitir la compatibilidad con programas anteriores).

+0

Y el estándar (C89) no especifica qué sucede cuando escribe en un literal precisamente porque no deseaba especificar la forma exacta en que ocurre un bloqueo, y porque también querían permitir que los compiladores admitan cadenas de escritura si querían (por ejemplo, a través de un interruptor; gcc tiene '-fwritable-strings' para hacer ese tipo de cosas, aunque la necesidad de eso es solo una indicación de un programa mal roto si me preguntas). –

1

El valor es un literal de cadena que no se puede modificar porque los literales se almacenan en la memoria de solo lectura, pruebe p [] en su lugar. Los errores deseguridad generalmente ocurren debido al uso incorrecto de los punteros.

Cuestiones relacionadas