Утечка памяти простая с - PullRequest
0 голосов
/ 28 апреля 2018

Я написал этот код для сортировки имен, и код работает, но в конце программы всегда возникает ошибка: ошибка в куче. Может кто-нибудь помочь мне понять, почему это происходит и как это исправить? Мой код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEMP_SIZE 50
void swap(char *str1, char *str2);
int main(void)
{
    int number = 0, i = 0, j = 0;
    char** names = 0;
    char temp[TEMP_SIZE] = { 0 };
    printf("Enter number of friends: ");
    scanf("%d", &number);
    names = (char**)malloc(number * sizeof(char*));
    for (i = 0; i < number; i++)
    {
        printf("Enter name of friend %d: \n", i + 1);
        scanf("%s", temp);
        names[i] = (char*)malloc(strlen(temp) * sizeof(char) + 1);
        strcpy(names[i], temp, strlen(temp) + 1);
    }
    for (j = 0; j < number - 1; j++)
    {
        for (i = 0; i < number - 1; i++)
        {
            if (strcmp(names[i], names[i + 1]) > 0)
            {
                swap(names[i + 1], names[i]);
            }
        }
    }
    for (i = 0; i < number; i++)
    {
        printf("Friend %d: %s\n", i + 1, names[i]);
    }
    for (i = number - 1; i >= 0; i--)
    {
        free(names[i]);
    }
    free(names);
    getchar();
    getchar();
    return 0;
}
void swap(char *str1, char *str2)
{
    char *temp = 0;
    temp = (char *)malloc((strlen(str1) + 1) * sizeof(char));
    strcpy(temp, str1);
    strcpy(str1, str2);
    strcpy(str2, temp);
    free(temp);
}

Буду рад и благодарен, если вы мне поможете!

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Проблема с вашей функцией swap состоит в том, что она ожидает, что обе строки имеют одинаковой длины или что оба места памяти достаточно велики, чтобы держать строки. Рассмотрим этот пример:

char str1[] = "Hello";
char str2[] = "This is a so much longer string";

swap(str1, str2);

произойдет сбой, потому что str1 недостаточно велик для хранения содержимого str2, поэтому strcpy вызовы будут записывать за пределы памяти, таким образом, вы переполнены буфер. Это проблема, с которой вы сталкиваетесь.

Вы должны решить:

  1. выделить, например, 1024 байта для каждого name[i], независимо от длины имени. Можно предположить, что ни одно имя не длиннее 1024 символов. (Не делай этого, уродливое решение).
  2. Вместо того, чтобы менять содержимое, меняйте местами указатели. Это гораздо проще сделать потому что names - это char**, а name[i] - это char* с, так что поменяйте местами указатели легко, так как вам не нужно беспокоиться о длине памяти, которую они указывая на.

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

void swap_ptrs(char **x, char **y)
{
    char *tmp = *x;
    *x = *y;
    *y = tmp;
}

и вместо звонка

swap(names[i + 1], names[i]);

звоните:

swap_ptrs(names + i + 1, names + i);

, который поменяет указатели.

редактировать

Я понимаю, что вам даже не нужна функция swap_ptrs для этого, вы можете сделать это так:

if (strcmp(names[i], names[i + 1]) > 0)
{
    char *tmp = names[i];
    names[i] = names[i + 1];
    names[i + 1] = tmp;
}

И, как указывает jspcal , самым элегантным и надежным решением было бы использование qsort:

int comp(const void *x, const void *y)
{
    const char *a = *((const char **) x);
    const char *b = *((const char **) y);
    return strcmp(a, b);
}

int main(void)
{
    ...

    qsort(names, number, sizeof *names, comp);

    ...
}
0 голосов
/ 28 апреля 2018

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

Вы также можете просто использовать stdlib qsort для сортировки массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...