【问题标题】:Memory leak plain c内存泄漏普通 c
【发布时间】:2018-04-27 23:27:28
【问题描述】:

我编写了这段代码来对名称进行排序并且代码可以工作,但是程序结束时总是出现错误,错误是:堆损坏。有人可以帮助我了解为什么会发生这种情况以及如何解决它吗? 我的代码:

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

如果你能帮助我,我会很高兴和感激!

【问题讨论】:

  • strcpy(names[i], temp, strlen(temp) + 1) 怎么编译?你确定这是你的实际代码吗?
  • 是的,我在 vs 运行它

标签: c memory memory-leaks


【解决方案1】:

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

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

【讨论】:

  • 我不想用qsort还有什么办法吗?
【解决方案2】:

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,所以交换指针 很容易,因为您不必担心它们的内存长度 指向。

交换函数可能如下所示

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

    ...
}

【讨论】:

  • 非常感谢您的帮助我现在明白了。您对我的帮助很大!!!
猜你喜欢
  • 2016-01-27
  • 2010-11-11
  • 2017-02-18
  • 1970-01-01
  • 2015-11-19
  • 2014-11-01
  • 2020-03-31
  • 2016-03-15
  • 2015-07-25
相关资源
最近更新 更多