【问题标题】:heap corruption when using free()使用 free() 时堆损坏
【发布时间】:2016-12-02 15:18:54
【问题描述】:

我是 c 中动态分配的新手,在调用 free() 函数时遇到堆损坏错误。

整个代码应该模拟重新分配函数realloc(),直到最后都可以正常工作。我在调试器模式下逐步运行代码多次,最后出现错误。如果有人可以帮助我,我将不胜感激。

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


void realocare(int **v, int n,int m)
{
    int *aux;
    unsigned int i;

    aux = (int*)malloc(m*sizeof(int));

    for (i = 0; i < m; i++)
        aux[i] = v[i];

    *v = (int*)malloc(n*sizeof(int));

    for (i = 0; i < m; i++)
        v[i] = aux[i];
    free(aux);
}

void afisare(int *v, int n,int i)
{
    for (i = 0; i < n; i++)
        printf_s("%d ", v[i]);

        printf_s("\n");
}

int main()
{
    int *v;
    unsigned int n,i,m;

    scanf_s("%u", &n);

    v = (int*)malloc(n*sizeof(int));

    for (i = 0; i < n; i++)
        scanf_s("%d", &v[i]);

    m = n;
    printf("%d", m);
    afisare(v, n, i);
    n++;
    realocare(&v, n,m);
    v[n - 1] = 9000;
    afisare(v, n, i);

    free(v);
    return 0;
}

【问题讨论】:

标签: c dynamic malloc free dynamic-allocation


【解决方案1】:

你分配给vn元素

v = ... malloc(n*sizeof(int));

并分配m

for (i = 0; i < m; i++)
    v[i] = aux[i];

对于m 大于n 的情况:这样做会写入无效内存,并由此调用未定义的行为,因此从这一刻起任何事情都可能发生。

在您的特殊情况下,这很可能会弄乱内部内存管理结构,导致稍后调用 free() 失败。


对已传递给函数的变量所做的更改不会被调用者反映,因为 C 中的函数总是并且永远只是接收调用者传递的内容的副本。 p>

因此,例如,您分配给v 的新值对于realocare() 的调用者保持未知

您可以通过如下调整代码来解决此问题:

void realocare(int **ppv, int n, int m)  //reallocation simulation function
{
  int *aux;
  unsigned int i;

  aux = malloc(m*sizeof(int));

  for (i = 0; i < m; i++)
    aux[i] = (*ppv)[i];

  free(*ppv); // Free what you had, to not leak this memory.

  *ppv = malloc(n*sizeof(int));

  for (i = 0; i < m; i++)
    (*ppv)[i] = aux[i];

  free(aux);
}

然后这样称呼它:

realocare(&v, n, m);

您的代码使用了两次对malloc() 的调用和两次对free() 的调用。这是低效的。

查看以下内容(添加一些其他的不仅仅是外观上的更改):

void realocare(int **ppv, size_t n, size_t m)  // no need for negative sizes ...
{
  int * aux = malloc(n * sizeof *aux);
  size_t i = 0; // no need for negative counters ...

  for (;i < m; ++i)
  {
    aux[i] = (*ppv)[i];
  }

  free(*ppv); 

  *ppv = aux;
}

只有一个malloc 和一个free... :-)


为了完整起见,还有一个强大的版本:

int realocare(int **ppv, size_t n, size_t m)  
{
  int result = -1; // be pessimistic

  if (NULL == ppv)
  {
    errno = EINVAL;
  }
  else
  {
    int * aux = malloc(n * sizeof *aux);

    if (NULL != aux) 
    {
      size_t i = 0; 

      for (;i < m; ++i)
      {
        aux[i] = (*ppv)[i];
      }

      free(*ppv); 

      *ppv = aux;

      result = 0;  // return success! 
    }
  }

  return result;
}

这样称呼它:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>  // for errno

...

int main(void)
{
  ...

  if (-1 == realocare(&v, n, m))
  {
    perror("realocare() failed");
    exit(EXIT_FAILURE);
  }

【讨论】:

  • 谢谢,但我不确定我是否明白了,我做了以下更改,但它仍然不起作用:'void realocare(int **v, int n,int m) ', '*v = (int)malloc(n*sizeof(int)); 'realocare(&v, n,m);'
  • @rednefed:不客气。为了好玩,我添加了您自己的代码的剥离版本。
猜你喜欢
  • 2020-08-02
  • 1970-01-01
  • 2020-08-18
  • 2021-12-14
  • 2020-07-22
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
相关资源
最近更新 更多