c - 使用 free() 时堆损坏

标签 c dynamic malloc free dynamic-allocation

我是 c 语言动态分配的新手,在调用 free() 函数时出现堆损坏错误。

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

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

最佳答案

你分配给 v n 个元素

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

并分配m

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

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

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


对已传递给函数的变量所做的更改不会由调用者反射(reflect),因为 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);
  }

关于c - 使用 free() 时堆损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40935489/

相关文章:

c - 为什么这个函数最后需要 getchar()?我不明白为什么它在那里

c# - System.Dynamic 错误?

c - 无效的 free()/delete/delete[]/realloc()

python - 使用 Python 生成彩色图图像

C 程序 - 素数

javascript - 如何将动态数据从sql插入到chartjs堆叠条形图javascript中

java - 用于热类重载的各种Java插件之间有什么区别,哪个最直观?

c - 执行 free() 时出错,显示 "glibc detected double free or corruption"

c++ - C++ 中 SSE 的内存对齐,_aligned_malloc 等效?

c - 错误地址 C(命令行解释器)