2010-12-11 13 views
7

sólo para las pruebas que había creado el siguiente código:fallo de segmentación en el programa c

#include<stdio.h> 

int main(){ 
    char *p = "Hello world"; 
    *(p+1) = 'l'; 
    printf("%s", p); 
    return 0; 
} 

Pero cuando me encontré con este por encima de mi "gcc" compilador bajo Ubuntu 10.04 que tengo:

Segmentation fault 

Así ¿Alguien puede explicar esto por qué sucedió esto?

#include<stdio.h> 
#include<stdlib.h> 

int main(){ 
    char *p = malloc(sizeof(char)*100); 
    p = "Hello world"; 
    *(p+1) = 'l'; 
    printf("%s", p); 
    free(p); 
    return 0; 
} 

esto también causar un fallo de segmentación Gracias de antemano

+0

posible duplicado de [¿Por qué código C sencilla ¿recibe una falla de segmentación?] (http://stackoverflow.com/questions/164194/why-does-simple-c-code-receive-segmentation-fault) – Joe

+4

... y alrededor de 2 docenas de otras preguntas de SO en los últimos años . – Joe

Respuesta

6

char *p = "Hello world"; *(p+1) = 'l';

Modiying el contenido de una cadena literal (es decir "Hola Mundo" en su código) es un comportamiento indefinido.

ISO C99 (Sección 6.4.5/6)

Es especi fi ed si estas matrices son distintos siempre que sus elementos tienen los valores apropiados. Si el programa intenta modificar una matriz de este tipo, el comportamiento está indefinido.

Intente utilizar una matriz de caracteres.

char p[] = "Hello World"; 
p[1] = 'l'; 

EDITAR

Su código modificado

#include<stdio.h> 
#include<stdlib.h> 
int main() 
{ 
    char *p = malloc(sizeof(char)*100); 
    p = "Hello world"; // p now points to the string literal, access to the dynamically allocated memory is lost. 
    *(p+1) = 'l'; // UB as said before edits 
    printf("%s", p); 
    free(p); //disaster 
    return 0; 
} 

invoca un comportamiento indefinido, así porque usted está tratando de cancelar la asignación de la sección de la memoria (usando free) que no ha sido asignado usando malloc

+0

hey, por favor, compruebe la pregunta modificada – codeomnitrix

+0

... y porque la memoria de solo lectura todavía se está modificando, ya que después de 'p =" Hello world "' p ya no apunta a la memoria 'malloc'ed. – Vlad

+0

bien, eso significa que la memoria previamente asignada (a través de malloc) se ha perdido y ahora lo que estoy usando es una nueva parte de la memoria asignada por el compilador para el literal de cadena "Hola mundo". Estoy en lo correcto? – codeomnitrix

2

Debido char *p = "Hello world" casi seguro que le ha dado un puntero a memoria de sólo lectura y eso significa que tratar de cambiarlo con *(p+1) = 'l' es un no- definitivo no (incluso si la memoria no es de solo lectura, el comportamiento aún no está definido).

La parte pertinente de C99 en referencia a los literales de cadena está en 6.4.5 para 6:

Es sin especificar si estas matrices son distintos siempre que sus elementos tienen los valores apropiados . Si el programa intenta modificar dicha matriz, el comportamiento es indefinido.


La razón por la que todavía obtener un fallo de segmentación con algo como:

char *p = malloc (100); // sizeof(char) is ALWAYS 1 
p = "Hello";    // better would be: strcpy (p, "Hello") 
*p = 'a'; 

se debe a que, a pesar de que estés asignación de memoria que se le permite modificar, la la segunda declaración cambia el puntero para apuntar a un literal de cadena (lo que le da una pérdida de mmory a medida que pierde el acceso a la memoria asignada), que no puede modificar.

Debe diferenciar los cambios en el puntero de los cambios a los que apunta el puntero en.

+0

pero cuando escribí p = "Hii". no da ningún problema – codeomnitrix

+0

Esto se debe a que está cambiando el puntero para que apunte a otro literal de cadena, _not_ no intente cambiar el literal de la cadena. – paxdiablo

+0

bien, pero ¿y si la memoria se asigna a través de malloc. como lo había hecho en la nueva sección de código de mi problema. – codeomnitrix

1

"Hello world" es un cadena literal. Se representa mediante un fragmento de bytes en una región de memoria que no se puede modificar . char *p puntos en ese trozo de bytes. *(p+1) = 'l' dice sobrescribir el siguiente byte después del apuntado con una 'l'. El siguiente byte después del apuntado es parte del fragmento que no se puede modificar. Intentar sobrescribir algo está intentando modificarlo. Intentar modificar algo que no se permite modificar es muy malo.

Para tener una copia del texto en la memoria que puede modificar, ponerlo en una matriz, p. char p[] = "Hello world";. (Tenga en cuenta que la declaración de la matriz de esta manera hace que sea exactamente lo suficientemente grande como para contener la cadena, y por lo tanto no puede alargar ella, ya que no hay más espacio.)

Cuestiones relacionadas