内存泄漏平原c

时间:2018-04-27 23:27:29

标签: c memory memory-leaks

我写了这个代码来对名称进行排序,代码可以正常运行,但是程序结束时总是出现错误:堆坏了。有人可以帮我解释它为什么会发生以及如何修复它? 我的代码:

#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 :(得分:3)

当字符串长度不同时,上面的swap函数将覆盖已分配字符串的边界,从而破坏堆。您可能只想交换存储在names数组索引中的指针,而不是覆盖已分配的字符串缓冲区的内容。

您也可以使用stdlib qsort对数组进行排序。

答案 1 :(得分:1)

swap函数的问题在于它期望两个字符串都有 相同的长度或两个存储位置足够大以容纳 字符串。考虑这个例子:

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

swap(str1, str2);

会崩溃,因为str1不足以存储str2的内容,所以 strcpy调用将超出内存限制,因此您会溢出 缓冲区。这是您面临的问题。

你需要解决方案:

  1. 为每个name[i]分配1024个字节,无论长度如何 这个名字。我们可以假设没有名称超过1024个字符。 (不要这么做,丑陋的解决方案)。
  2. 而不是交换内容,交换指针。这样做要容易得多 因为nameschar**name[i]char* s,所以交换指针 很容易,因为你不必担心它们的记忆长度 指着。
  3. 交换功能可能如下所示

    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);
    
        ...
    }