segmentation raspberry dumped debug c pointers segmentation-fault

c - dumped - segmentation fault raspberry pi



Accidente o "falla de segmentación" cuando los datos se copian/escanean/leen a un puntero no inicializado (5)

Esta pregunta está destinada a ser utilizada como referencia para todas las preguntas frecuentes de la naturaleza:

¿Por qué obtengo una falla misteriosa o "falla de segmentación" cuando copio / escaneo datos a la dirección a la que apunta un puntero no inicializado?

Por ejemplo:

char* ptr; strcpy(ptr, "hello world"); // crash here!

o

char* ptr; scanf("%s", ptr); // crash here!


  1. Los punteros solo apuntan a una ubicación de memoria. Creó un puntero pero aún no se unió a una ubicación de memoria. strcpy quiere que pases dos punteros (el primero no debe ser constante ) que apunten a dos matrices de caracteres como esta firma:

    char * strcpy ( char * destination, const char * source );

    uso de muestra:

    char* ptr = malloc(32); strcpy(ptr, "hello world");

    char str[32]; strcpy(str, "hello world");

  2. Puede probar el siguiente fragmento de código para leer la cadena hasta llegar al carácter de nueva línea (* también puede agregar otros caracteres de espacio en blanco como "%[^/t/n]s" ( tab, nueva línea ) o "%[^ /t/n]s" ( espacio, tabulación, nueva línea )).

    char *ptr = malloc(32); scanf("%31[^/n]", ptr);

    (¡En la vida real, no olvides comprobar el valor de retorno de scanf() !)


Esto sucede porque no ha asignado memoria para el puntero char* ptr . En este caso, debe asignar dinámicamente memoria para el puntero.

Se pueden usar dos funciones malloc() y calloc() para dynamic memory allocation .

Prueba este código: -

char* ptr; ptr = malloc(50); // allocate space for 50 characters. strcpy(ptr, "hello world");

Cuando el uso de *ptr over no olvide desasignar la memoria asignada para *ptr . Esto se puede hacer usando free() función free() .

free(ptr); // deallocating memory.

El tamaño de la memoria asignada dinámicamente se puede cambiar usando realloc() .

char *tmp = realloc(ptr, 100); // allocate space for 100 characters. if (! tmp) { // reallocation failed, ptr not freed perror("Resize failed"); exit(1); } else { // reallocation succeeded, old ptr freed ptr = tmp; }

En la mayoría de los casos, se produce un "error de segmentación" debido a un error en la asignación de memoria o una matriz fuera de los casos vinculados .


No es este el caso, pero una situación que ocurre con frecuencia al principio es cuando se utilizan comillas simples y se intenta definir un literal de cadena como:

char ptr[5]; strcpy(ptr, ''hello''); // crash here! ^ ^ // because of '' instead "

En C ''h'' es un literal de un solo carácter, mientras que "h" es un literal de cadena que contiene una ''h'' y un terminador nulo / 0 (que es una matriz de 2 caracteres). Además, en C, el tipo de literal de caracteres es, es decir, sizeof ''h'' es 4 (en 32 bits), mientras que sizeof (char) es 1.

char h = ''h''; printf("Size: %d/n",sizeof(h)); //Size: 1 printf("Size: %d/n",sizeof(''h'')); //Size: 4


Para hacer una copia modificable de una cadena, en lugar de usar malloc , strlen y strcpy , la biblioteca POSIX C tiene una función práctica llamada strdup en <string.h> que devolverá una copia de la cadena terminada en nulo pasada con asignación asignada duración del almacenamiento Después de usar el puntero se debe liberar con free :

char* ptr; ptr = strdup("hello world"); ptr[0] = ''H''; puts(ptr); free(ptr);


Un puntero es un tipo especial de variable, que solo puede contener una dirección de otra variable. No puede contener ningún dato. No puede "copiar / almacenar datos en un puntero", eso no tiene ningún sentido. Solo puede establecer un puntero para apuntar a los datos asignados en otro lugar.

Esto significa que para que un puntero sea significativo, siempre debe apuntar a una ubicación de memoria válida. Por ejemplo, podría apuntar a la memoria asignada en la pila:

{ int data = 0; int* ptr = &data; ... }

O memoria asignada dinámicamente en el montón:

int* ptr = malloc(sizeof(int));

Siempre es un error utilizar un puntero antes de que se haya inicializado. Todavía no apunta a una memoria válida.

Todos estos ejemplos podrían conducir a bloqueos del programa u otros tipos de comportamiento inesperado, como "fallas de segmentación":

/*** examples of incorrect use of pointers ***/ // 1. int* bad; *bad = 42; // 2. char* bad; strcpy(bad, "hello");

En su lugar, debe asegurarse de que el puntero apunta a (suficiente) memoria asignada:

/*** examples of correct use of pointers ***/ // 1. int var; int* good = &var; *good = 42; // 2. char* good = malloc(5 + 1); // allocates memory for 5 characters *and* the null terminator strcpy(good, "hello");

Tenga en cuenta que también puede establecer un puntero para que apunte a un "lugar" bien definido, dejándolo apuntar a NULL . Esto lo convierte en un puntero nulo , que es un puntero que se garantiza que no apuntará a ninguna memoria válida. Esto es diferente de dejar el puntero completamente sin inicializar.

int* p1 = NULL; // pointer to nowhere int* p2; // uninitialized pointer, pointer to "anywhere", cannot be used yet

Sin embargo, si intenta acceder a la memoria apuntada por un puntero nulo, puede obtener problemas similares a los que se producen al usar un puntero no inicializado: bloqueos o fallas de segmentación. En el mejor de los casos, su sistema se da cuenta de que está intentando acceder a la dirección nula y luego lanza una "excepción de puntero nulo".

La solución para los errores de excepción de puntero nulo es la misma: debe configurar el puntero para que apunte a la memoria válida antes de usarlo.

Otras lecturas:

Punteros apuntando a datos no válidos
¿Cómo acceder a una variable local desde una función diferente usando punteros?
¿Se puede acceder a la memoria de una variable local fuera de su alcance?

Falla de segmentación y causas
¿Qué es una falla de segmentación?
¿Por qué aparece un error de segmentación al escribir en una cadena inicializada con "char * s" pero no "char s []"?
¿Cuál es la diferencia entre char s [] y char * s?
Lista definitiva de razones comunes para fallas de segmentación
¿Qué es un error de bus?