La implementación de strcat() funciona pero provoca un volcado del núcleo al final

6 minutos de lectura

La implementacion de strcat funciona pero provoca un volcado del
Registro de datos

Mi implementación de strcat(char*, const char*) parece funcionar, pero luego provoca un volcado del núcleo.

strcat() implementación:

char* strcat(char* dest, const char* src)
{
    char* tmp = dest;
    while(*tmp) ++tmp ;
    while( (*tmp++ = *src++ ) != '\0') ;
    return (dest);
}

Código en int main() donde llamo strcat():

char arr3[] = "Mr. ";
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));

En realidad, concatenó ambas cadenas y las imprimió, pero aun así provocó un volcado del núcleo.

producción : ¡Hola, Sr. Smith! Abortado (núcleo descargado)

¿Qué hice mal?

  • Aunque es antiguo y ha aceptado, pero leyó la respuesta actualizada, agregó algunos detalles interesantes …

    –Grijesh Chauhan

    08/07/2013 a las 18:15


  • Bien gracias. Lo haré en unos segundos 😉

    – Davlog

    12 de julio de 2013 a las 15:36

  • Probablemente se deba a que cuando no especifica un tamaño, la matriz elige automáticamente el tamaño ideal para adaptarse a su contenido. Entonces arr3 tiene 5 bytes de largo, y agregando "Smith" requiere una cadena de 10 bytes. Por qué es un volcado del núcleo en lugar de una falla de segmentación, no puedo decirle.

    – Braden Mejor

    3 de enero de 2016 a las 23:54

La implementacion de strcat funciona pero provoca un volcado del
grijesh chauhan

Tu programa haciendo desbordamiento de búfer en tiempo de ejecución, por strcat(arr3, arr4) porque arr3 el tamaño es igual a la longitud de "Mr." string , no tiene espacio de memoria adicional para caracteres adicionales (de arr4).

tamaño de arr3 debe tener al menos una longitud de cadena de un "Mr. " + "Smith" + 1

(1 adicional para terminación de cadena \0 carbonizarse)

Mi sugerencia es usar la asignación de memoria dinámica para un búfer de tamaño suficiente, haga algo como el código a continuación:

char arr3[] = "Mr. ";
char arr4[] = "Smith";
length = strlen(arr3) + strlen(arr4) + 1;  //cal-length (sufficient long buffer)
char* new_arr = malloc(length);  // allocate memory 
strcpy(new_arr, arr3);  // copy first string 
strcat(new_arr, arr4);  // then check your function to concat strings

Motivo del volcado de núcleo:

En tu código:

char arr3[] = "Mr. ";

La talla de arr2 es = longitud de la cadena "Mr." longitud + 1 (1 por \0) caracteres. los strcat() primeros movimientos temp punteros para apuntar nulo en el primer ciclo while while(*tmp) ++tmp ;.

Después de eso en el segundo bucle while while( (*tmp++ = *src++ ) != '\0') ; está intentando acceder y asignar una memoria que no está asignada (es posible que esté fuera de su control de proceso) y acceder a una memoria que no ha asignado es un comportamiento indefinido en C.

Editar:

En codigo arr3 es algo como a continuación en el diagrama, donde temp puntos a arr3 formación:

                arr3

   temp          5   6  7  8    
  +-----+      +--+--+--+---+
  | 5   +----->|M |r |. |\0 |
  +-----+      +--+--+--+---+

cuando bucle while(*tmp) ++tmp ; descansos temp comienza a apuntar a la ubicación de la memoria 8 donde nulo \0 se almacena, como el siguiente diagrama.

                arr3

   temp          5   6  7  8    
  +-----+      +--+--+--+---+
  | 8   |      |M |r |. |\0 |
  +-----+      +--+--+--+---+
     |                    ^
     +--------------------|

Cuando tu lo hagas temp++ en bucle while( (*tmp++ = *src++ ) != '\0') ; , temp incremento para apuntar a la ubicación de la memoria 9 y en adelante, pero acceso y asignación en la memoria 9, 10.. es ilegal porque no está asignado. Esto hace que el kernel del sistema operativo envíe una señal volcado de memoria al proceso que causó la excepción. (interesante notar: ya que el sistema operativo detecta una violación de los derechos de memoria por parte de un proceso: un acceso no válido a una memoria válida da: SIGSEGV y el acceso a una dirección no válida da: SIGBUS).

Señales de error del programa:

Cuando una de estas señales de error de programa termina un proceso, también escribe un archivo de volcado central que registra el estado del proceso en el momento de la terminación. El archivo de volcado del núcleo se llama ‘core’ y está escrito en cualquier directorio que esté actual en el proceso en ese momento. (En el sistema GNU, puede especificar el nombre de archivo para los volcados del núcleo con la variable de entorno COREFILE). El propósito de los archivos de volcado del núcleo es que pueda examinarlos con un depurador para investigar la causa del error.

Si asigna memoria adicional (como sugirieron @JerryCoffin y @Paul R), entonces puede acceder a la memoria más allá \0 (ubicación de la memoria 8) no es problema.

Nota: Si no da el tamaño en la declaración, el tamaño de la matriz será igual al tamaño de la cadena, por ejemplo, en char arr3[] = "Mr. "; el tamaño es 5. Pero si das el tamaño explícitamente como char arr3[84] = "Mr. "; entonces el tamaño de aar3 sera 84 y la memoria inicial contiene Mr. luego 0 en el resto de todas las localidades.

En mi solución, asigno completamente nuevos bloques de memoria que son tan grandes como ambas cadenas arr3 y arr4 se puede almacenar con un símbolo nulo utilizando la asignación de memoria dinámica (malloc() función). Además, si asigna memoria dinámica usando ptr = malloc() o ptr = calloc() entonces deberías liberar memoria explícitamente cuando termines el trabajo usando free(ptr).

  • Entonces, ¿lo único que me impide ir más allá del ‘\ 0’ es el kernel del sistema operativo? En una máquina sin sistema operativo, ¿podría ir más allá?

    – Davlog

    12 de julio de 2013 a las 15:41

  • @Davlog No '\0', pero más allá del espacio asignado. ¿Cómo puede ejecutar su código C simple en una máquina sin sistema operativo (la segunda pregunta no es válida)?

    –Grijesh Chauhan

    12 de julio de 2013 a las 15:49

No ha asignado ningún espacio adicional en str3 así que intentar agregar caracteres usando strcat desbordará el almacenamiento asignado; cambie su código a, por ejemplo:

char arr3[80] = "Mr. "; // <<< allocate additional storage for appending more characters
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));

El problema no es con tu strcat, pero con la forma en que lo está usando/invocando. Está escribiendo más allá del final de la matriz de destino.

Cambiar arr3 a algo como char arr3[32] = "Mr. "; y todo estará bien.

  • ¿Funcionaría si uso malloc() dentro de la función para dest?

    – Davlog

    25 mayo 2013 a las 15:26

  • El problema básico de @Davlog es que arr3 es pequeño, no tiene espacio adicional para acomodar caracteres adicionales de arr4incluso si asigna memoria usando malloc() lo harás strcat() funciona si asigna espacios adicionales

    –Grijesh Chauhan

    25 mayo 2013 a las 15:44

  • @Davlog: podría, por ejemplo, asignar un nuevo bloque de memoria del tamaño de ambas cadenas de entrada (+1 para un terminador NUL) y crear una cadena concatenada allí. Eso sería diferente de cómo strcat aunque normalmente funciona.

    – Jerry Ataúd

    25 mayo 2013 a las 16:02

¿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