#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "huffman.h"

// Structures defined here.
struct hmNode {
  struct hmNode *left;
  char ch;
  freq f;
  bool used;
  struct hmNode *right;
};
typedef struct hmNode hmNode;

struct nodeArr {
  int capacity;
  struct hmNode **arr;
};
typedef struct nodeArr nodeArr;

//-----------------------------------------------------------------------------
// Functions defined here.

hmNode *new_node(char ch, freq f){
  hmNode *p = malloc(sizeof(hmNode));
  *p = (hmNode) {NULL, ch, f, false, NULL};
  return p;
}

nodeArr *make_arr(char *chs, freq  *fs){
  nodeArr *nodeArr = malloc(sizeof(nodeArr));
  int n = strlen(chs);
  nodeArr->capacity = n;
  nodeArr->arr = malloc( sizeof(hmNode*) * (n+1) );
  for(int i=0; i<nodeArr->capacity; i++){
    nodeArr->arr[i] = new_node(chs[i], fs[i]);
  }
  nodeArr->arr[nodeArr->capacity] = new_node('\0', -1);
  return nodeArr;
}

int extract_min_idx(nodeArr *nodeArr){
  int smaller;
  hmNode **arr = nodeArr->arr;
  int idx = 0;
  while(arr[idx]->used) idx++;
  smaller = idx;
  int val = arr[idx]->f;
  while(idx < nodeArr->capacity){
    idx++;
    while(arr[idx]->used) idx++;
    if(arr[idx]->ch != '\0' && arr[idx]->f < val) {
      val = arr[idx]->f;
      smaller = idx;
    }
  }
  arr[smaller]->used = true;
  return smaller;
}

void insert_node(nodeArr *nodeArr){
  int s1 = extract_min_idx(nodeArr);
  int s2 = extract_min_idx(nodeArr);
  hmNode *new = malloc(sizeof(hmNode));
  new->left = nodeArr->arr[s1];
  new->right = nodeArr->arr[s2];
  new->f = new->left->f + new->right->f;
  new->used = false;
  nodeArr->arr[s1] = new;
}

bool is_tree_done(nodeArr *nodeArr){
  int cnt = 0;
  for(int i=0;i<nodeArr->capacity;i++){
    if(!(nodeArr->arr[i]->used)) cnt++;
  }
  if(cnt == 1) return true;
  else return false;
}

//void free_nodeArr(nodeArr *nodeArr){
//  for(int i=0;i<nodeArr->capacity; i++){
//    free(nodeArr->arr[i]);
//    }
//  free(nodeArr->arr[nodeArr->capacity]);
//  free(nodeArr->arr);
//  free(nodeArr);
//}

hmNode *build_tree(char chs[], freq fs[]){
  hmNode *root;
  nodeArr *nodeArr = make_arr(chs, fs);
  while(!(is_tree_done(nodeArr))){
    insert_node(nodeArr);
  }
  for(int i=0;i<nodeArr->capacity;i++){
    if(!(nodeArr->arr[i]->used)) {
      root = nodeArr->arr[i];
      root->used = true;
    }
  }
  return root;
}

int is_leaf(hmNode *hmNode){
  return !(hmNode->left) && !(hmNode->right);
}

void encode(hmNode *root, int idx, char code[]){
  if(root->left){
    code[idx]='0';
    encode(root->left, idx + 1, code);
  }
  if(root->right){
    code[idx]='1';
    encode(root->right, idx + 1, code);
  }
  if(is_leaf(root)){
    printf("%c: ", root->ch);
    printf("%s\n", code);
  }
}

// void free_tree(hmNode *root){
//   if(is_leaf(root))
//   free_tree(root->left);
//   free_tree(root->right);
//   free(root);
// }
//-----------------------------------------------------------------------------
// Tests

void test_new_node(){
  char chs[] = "ab";
  freq fs[] = {1,2};
  hmNode *new = new_node(chs[0], fs[0]);
  assert(new->ch  == 'a');
  assert(new->f == 1);
  free(new);
}

void test_new_arr(){
  char chs[] = "ab";
  freq fs[] = {1,2};
  nodeArr *newArr = make_arr(chs, fs);
  assert(newArr->arr[0]->ch == 'a');
  assert(newArr->arr[0]->f  ==  1);
  assert(newArr->arr[1]->ch == 'b');
  assert(newArr->arr[1]->f  ==  2);
  assert(newArr->arr[2]->ch == '\0');
  assert(newArr->arr[2]->f  ==  -1);
  //free_nodeArr(newArr);
}

//-----------------------------------------------------------------------------
int main(){
  test_new_node();
  test_new_arr();
  printf("Completed\n");

  //hmNode *root = build_tree(chs, fs);
  //free_tree(root);
  // printf("%d\n", root->f);
  // printf("%d\n", root->left->f);
  // printf("%d\n", root->right->f);
  // printf("%d\n", root->right->left->f);
  // printf("%d\n", root->right->right->f);
  // char code[10];
  // encode(root, 0, code);

  return 0;
}


我尝试使用优先级排队算法构建霍夫曼树,并在使用'clang -std = c11 -Wall -pedantic -g(NAMEOFTHEFILE).c -o(NAMEOFTHEFILE)'对其进行编译时检查了它是否工作。但是,当我使用'clang -std = c11 -Wall -pedantic -g(NAMEOFTHEFILE).c -o(NAMEOFTHEFILE)-fsanitize = undefined -fsanitize = address -fsanitize = leak对其进行编译时,它一直在说'堆缓冲区溢出',我想'make_arr'函数存在问题。

谁能告诉我如何处理此错误?

最佳答案

您的问题在这里:

 nodeArr *nodeArr = malloc(sizeof(nodeArr));


sizeof(nodeArr)是指针的sizeof(8),而不是具有相同名称的结构的sizeof(16)。这是将变量的名称与类型命名不是一个好主意的众多原因之一。

您应该考虑配置ASAN_SYMBOLIZER_PATH,以便在清理时拥有更好的符号。我就是这样找到的。

关于c - 试图用C制作霍夫曼树,但一直说堆溢出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53602052/

10-14 15:28