【问题标题】:C pointer being freed was not allocated被释放的 C 指针未被分配
【发布时间】:2014-06-14 21:27:41
【问题描述】:

我做了这个 BinaryTree 实现,除了 freeTree() 方法说我正在尝试释放一个未分配的指针之外,它工作正常。我只是找不到我的逻辑在这里出错的地方。 我不知道如何准确找到它所在的指针。 有什么提示、技巧吗?

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

struct BinaryTree
{
    int data;
struct BinaryTree *left;
struct BinaryTree *right;
};

typedef struct BinaryTree BinaryTree;

FILE *input;
FILE *output;

char dat[99];
int number;

BinaryTree tree;

void add(int data, BinaryTree *tree);
void inorderTraversal(BinaryTree *tree);
void freeTree(BinaryTree *tree);

int main()
{
input = fopen("/Users/sergeymikhaylyuk/Desktop/Program/Tree/input.txt", "r");
output = fopen("/Users/sergeymikhaylyuk/Desktop/Program/Tree/sorted.txt", "w");
while (fgets(dat, sizeof(dat), input))
{
    sscanf(dat, "%i", &number);
    add(number, &tree);
}
inorderTraversal(&tree);
freeTree(&tree);

}

void add(int data, BinaryTree *tree)
{
if (tree->data == 0)
{
    tree->data = data;
}
else
{
    if (tree->data < data && tree->right != NULL)
    {
        add(data, tree->right);
    }
    else if (tree->data < data)
    {
        tree->right = malloc(sizeof(BinaryTree));
        add(data, tree->right);
    }
    else if (tree->data > data && tree->left != NULL)
    {
        add(data, tree->left);
    }
    else if (tree->data > data)
    {
        tree->left = malloc(sizeof(BinaryTree));
        add(data, tree->left);
    }
}
}

void inorderTraversal(BinaryTree *tree)
{
if (tree != NULL)
{
    if (tree->left != NULL)
    {
        inorderTraversal(tree->left);
    }
    fprintf(output, "%i ", tree->data);
    if (tree->right != NULL)
    {
        inorderTraversal(tree->right);
    }
}

}
int i = 1;
void freeTree(BinaryTree *tree)
{
printf("%i ", i);
i++;
if (tree != NULL)
{
    if (tree->left != NULL)
    {
        freeTree(tree->left);
    }
    if (tree->right != NULL)
    {
        freeTree(tree->right);
    }
    free(tree);
}
}

【问题讨论】:

    标签: c pointers binary-tree


    【解决方案1】:

    因为这一行,根节点在栈上

    BinaryTree tree;
    

    所有其他节点都在堆上。

    但是你freeTree 可以释放所有节点,包括根。因此它给出了错误trying to free a pointer which hasn't been malloced error

    最简单的解决方法是将上述更改为

    BinaryTree * ptree = malloc(sizeof(BinaryTree));
    ptree->data = 0;
    ptree->left = NULL;
    ptree->right = NULL; 
    

    并将您使用&amp;tree 的所有位置更改为ptree

    例如。

    add(number, &tree);
    

    add(number, ptree);
    

    除此之外,您还需要在所有位置malloc 之后将左右初始化为 NULL。

    例如。之后

    tree->right = malloc(sizeof(BinaryTree));
    

    添加

    tree->right->data = 0;
    tree->right->left = NULL;
    tree->right->right = NULL;
    

    【讨论】:

      【解决方案2】:

      malloc 返回新分配的数据,但不对分配的结构进行零填充(初始化)。 因此,如果 left 和 right 是指针,它们指向一个随机的非零地址。因此,如果您尝试释放未分配的数据,就会出现这种情况。

      修复可能如下所示:

      
          ...
          tree->right = malloc(sizeof(BinaryTree));
          bzero(tree->right, sizeof(BinaryTree));
          add(data, tree->right);
          ...
      

      【讨论】:

      • 初始化数据和分配内存不一样,你可以free你没有初始化的内存(或以任何方式触摸),例如:ideone.com/2D4Dc3
      • OK 解释清楚。
      【解决方案3】:

      当您分配节点时,您永远不会在使用它们之前对其进行初始化。 malloc() 返回的项目不保证初始化为零(或任何其他特定值)。所以你leftright 链接指针可能有垃圾值。你应该这样做:

      BinaryTree* alloc_node(void)
      {
          BinaryTree* p = malloc(sizeof(BinaryTree));
          if (p) {
              p->data = 0;
              p->left = p->right = 0;
          }
          return p;
      }
      

      并调用alloc_node() 而不是malloc() 来分配新节点。

      【讨论】:

      • 如果无论如何默认为零,将数据分配给0的目的是什么?
      • 正如我所说,“malloc() 返回的项目不保证初始化为零(或任何其他特定值)”。
      • 使用值NULL,表示一个空指针,而不是值0,它是一个整数。
      • @user3614293 除非您使用 calloc,否则不会自动为您初始化内存
      猜你喜欢
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      相关资源
      最近更新 更多