简体   繁体   English

细分错误是由于重新分配引起的?

[英]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. 串联应该在一个函数中进行,如果成功则返回1,否则返回0。 for memory allocation use only realloc! 对于内存分配,只能使用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? 调试程序时没有收到任何错误,但是当我尝试运行该程序时,在插入字符串后,唯一出现的是“ Segmentation Fault”,这可能是什么? 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: 您的代码至少有5个问题:

1) You should free only what you allocated yourself on the heap. 1)您应该只free自己在堆上分配的内容。 Don't free(src) because what you pass in src points to stack memory ( char string[51]; is freed automatically). 不要free(src)因为您在src传递的内容指向堆栈内存( char string[51];自动释放)。

2) you probably meant to reallocate dest , and 3) you meant to allocate memory the size of length3 (+1 null-terminator). 2)您可能打算重新分配dest ,3)您打算分配长度为length3 (+1空终止符)的内存。

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

4) strlen(*dest) will crash when *dest is NULL initially. 4)当*dest最初为NULL时, strlen(*dest)将崩溃。

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

5) I don't think your for-loop is correct. 5)我认为您的for循环不正确。 It won't concatenate the strings, your offset calculation is off. 它不会连接字符串,偏移量计算已关闭。

The initial value of the pointer output is NULL. 指针output的初始值为NULL。 However inside the function there is no check that the pointer is equal to NULL. 但是在函数内部没有检查指针是否等于NULL。 So applying the function strlen to the pointer results in undefined behavior. 因此,将strlen函数应用到指针会导致未定义的行为。

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. 而且sizeof( *src )等于一个字节。

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. 您不应释放指针src因为它没有指向动态分配的内存。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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