简体   繁体   中英

Segmentation Fault caused by realloc?

Hei, I was trying to solve this school exercise..

Write a program that keeps reading in character strings and concatenates them (adds them to a single character string). the concatenation should take place in a function that returns 1 if successful or 0 if it fails. for memory allocation use only realloc!

I don't receive any error while debugging the program, but when I try to run the program, after I insert the string the only thing that appears is "Segmentation Fault", what could it be? This is the code:

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

int cat(char **, char *);

int main(void)
{
  char string[51];
  char *output=NULL;
  char choice;
  do
  {
    printf("Please enter a string [<50 chars]: ");
    fgets(string,50,stdin);
    if(string[strlen(string)-1]=='\n') /* if newline was read as well */
      string[strlen(string)-1]=0;      /* discard it */
    if(cat(&output,string))
      printf("\n\nThe string now contains:\n%s\n",output);
    else
    {
      printf("error: memory (re-)allocation failed!\n\n");
      return 1; /* exit with error */ 
    }
    printf("Continue? (y/n) - ");
    fgets(string,3,stdin); /* read input from keyboard - leave a safety buffer to account for read newline */
    choice=string[0]; /* use the first character from the previous read as the choice */
  } while(choice=='y' || choice=='Y');

  free(output);
  return 0;
}

int cat(char **dest, char *src)
{

  int i;
  int length1=strlen(src);
  int length2=strlen(*dest);
  int length3=length1+length2;
  *dest=(char*)realloc(NULL,sizeof(*src));
  printf("%p", *dest);
  if(*dest==NULL) return 0; /* if allocation failed */
  for(i=0;i<=length3;i++)
  {
      if(i<=length1)
        (*dest)[i]=(*dest)[i];
      else
        (*dest)[i]=(src)[i];
  }
  free(src);
  return 1;
}

There are at least 5 issues with your code:

1) You should free only what you allocated yourself on the heap. Don't free(src) because what you pass in src points to stack memory ( char string[51]; is freed automatically).

2) you probably meant to reallocate dest , and 3) you meant to allocate memory the size of length3 (+1 null-terminator).

    *dest=(char*)realloc(*dest, length3 + 1);

4) strlen(*dest) will crash when *dest is NULL initially.

    int length2=(*dest)?strlen(*dest):0;

5) I don't think your for-loop is correct. It won't concatenate the strings, your offset calculation is off.

The initial value of the pointer output is NULL. However inside the function there is no check that the pointer is equal to NULL. So applying the function strlen to the pointer results in undefined behavior.

Also you need to reserve one more character for the terminating zero.

The memory is not reallocated correctly in the function. Moreover sizeof( *src ) is equal to one byte.

This statement

  if(i<=length1)
    (*dest)[i]=(*dest)[i];

does not make great sense. The reallocated memory provided that it was reallocated correctly already contains the original string.

You shall not free the pointer src because it does not point to a dynamically allocated memory.

The function can look the following way as it is shown in the demonstrative program.

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

int cat( char **dest, const char *src )
{
    size_t n = strlen( src ) + ( *dest == NULL ? 0 : strlen( *dest ) );

    char *tmp = realloc( *dest, n + 1 );
    int success = tmp != NULL;

    if ( success )
    {
        if ( *dest == NULL ) *tmp = '\0';
        *dest = tmp;

        while ( *tmp ) ++tmp;

        while ( ( *tmp++ = *src++ ) );
    }       

    return success;
}   

#define N   50

int main(void) 
{
    char *output = NULL;
    char choice = 'n';

    do
    {
        char string[N];


        printf( "Please enter a string [<%d chars]: ", N );
        fgets( string, sizeof( string ),stdin );

        string[strcspn( string, "\n" )] = '\0';

        if ( cat( &output, string ) )
        {
            printf( "\nThe string now contains:\n\"%s\"\n\n", output );
        }           
        else
        {
            printf( "error: memory (re-)allocation failed!\n\n" );
            return 1; /* exit with error */ 
        }

        printf( "Continue? (y/n) - " );
        fgets( string, 3, stdin ); /* read input from keyboard - leave a safety buffer to account for read newline */
        choice = string[0]; /* use the first character from the previous read as the choice */
    } while ( choice == 'y' || choice == 'Y' );

    free( output );

    return 0;
}

Its output might look like

Please enter a string [<50 chars]: Hi Stefano Feltre

The string now contains:
"Hi Stefano Feltre"

Continue? (y/n) - y
Please enter a string [<50 chars]: 

The string now contains:
"Hi Stefano Feltre "

Continue? (y/n) - y
Please enter a string [<50 chars]: Let's learn C

The string now contains:
"Hi Stefano Feltre Let's learn C"

Continue? (y/n) - n

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM