Почему происходит коррупция в куче? - PullRequest
1 голос
/ 07 июня 2019

Я работал над некоторыми практическими проблемами для школы, и в одном из них вводимое целое число должно быть записано в динамически размещаемую строку. Код выполняет свою работу нормально, пока не добьется освобождения выделенной памяти, где происходит повреждение кучи.

Может кто-нибудь объяснить, почему это происходит и что я делаю не так?

int main() {

  char *string = NULL;
  char **string2 = &string;

  Conversion(string2);
  printf("Entered number converted to string: %s", string);
  free(string);

  return 0;
}

int Conversion(char **string) {

    int num = 0, temp = 0, dcount = 0;
    printf("Enter number: ");
    scanf(" %d", &num);

    temp = num;

    while (temp != 0) {
      temp /= 10;
      dcount++;
    }

    *string = (char*)malloc(dcount*sizeof(char));
    if (*string == NULL) {
      printf("Error during memory allocation!");
      return -1;
    }

    sprintf(*string, "%d", num);

    return 0;
}

Ответы [ 2 ]

5 голосов
/ 07 июня 2019

Вам необходимо выделить дополнительный символ для учетной записи для терминатора \0.

*string = (char*)malloc((dcount + 1) * sizeof(char));

Также dcount неверно, если num равно 0 или отрицательно.

Другоекомментарии:

2 голосов
/ 07 июня 2019

Функция имеет несколько недостатков.

Для начинающих вы не учитываете конечный ноль '\0' для выделенной строки.

Во-вторых, пользователь может ввести 0 как число. В этом случае значение dcount будет неправильным, поскольку цикл

while (temp != 0) {
  temp /= 10;
  dcount++;
}

будет пропущено.

В-третьих, функция не будет правильно обрабатывать отрицательные числа, и пользователю разрешено вводить отрицательные числа.

Эта декларация

char **string2 = &string;

является избыточным. Вы можете вызвать функцию следующим образом

Conversion( &string );

Это не та функция, которая должна запрашивать у пользователя ввод числа. Функция должна выполнять только одну задачу: преобразовать целое число в строку.

И еще один недостаток конструкции функции.

Из объявления функции

int Conversion(char **string); 

(которое должно предшествовать функции main) неясно, должен ли пользователь предоставлять память для строки или это функция, которая выделяет память для строки.

Улучшенный интерфейс функции может выглядеть следующим образом, как показано в демонстрационной программе ниже.

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

char * Conversion( int x )
{
    const int Base = 10;

    size_t digits = x < 0 ? 1 : 0;

    int tmp = x;

    do
    {
        ++digits;
    } while ( tmp /= Base );

    char *s = malloc( digits + sizeof( ( char )'\0' ) );

    if ( s != NULL ) sprintf( s, "%d", x );

    return s;
}

int main( void )
{
    int num = 0;

    printf( "Enter a number: " );
    scanf( "%d", &num );

    char *s = Conversion( num );

    if ( s != NULL )
    {
        printf( "The entered number converted to string: %s\n", s );
    }
    else
    {
        puts( "A conversion error ocured." );
    }

    free( s );
}

Его вывод может выглядеть следующим образом

Enter a number: -12
The entered number converted to string: -12

Примите во внимание, что согласно стандарту C функция main без параметров должна быть объявлена ​​как

int main( void )
...