【问题标题】:Binary tree code works on Linux but not on Windows 10二叉树代码适用于 Linux,但不适用于 Windows 10
【发布时间】:2021-08-01 06:13:13
【问题描述】:

我在 Linux 上运行的代码没有内存错误,并且在 Linux 上运行时树可以正确构建,但是当我在 Windows 上运行它时它会卡住并终止。

struct node {
    char letter;
    char *string;
    int last_node;
    struct node *left;
    struct node *right;
};

static struct node nodes[] =
{
    {'\0', ""},
    {'E', "."},
    {'T', "-"},
    {'I', ".."},
    {'A', ".-"},
    {'N', "-."},
    {'M', "--"},
    {'S', "..."},
    {'U', "..-"},
    {'R', ".-."},
    {'W', ".--"},
    {'D', "-.."},
    {'K', "-.-"},
    {'G', "--."},
    {'O', "---"},
    {'H', "...."},
    {'V', "...-"},
    {'F', "..-."},
    {'\0', "..--"},
    {'L', ".-.."},
    {'\0', ".-..-"},
    {'P', ".--."},
    {'J', ".---"},
    {'B', "-..."},
    {'X', "-..-"},
    {'C', "-.-."},
    {'Y', "-.--"},
    {'Z', "--.."},
    {'Q', "--.-"},
    {'\0', "---."},
    {'\0', "----"},
    {'5', "....."},
    {'4', "....-"},
    {'\0', "...-."},
    {'3', "...--"},
    {'\0', "..-.."},
    {'\0', "..-.-"},
    {'\0', "..--."},
    {'2', "..---"},
    {'\0', ".-..."},
    {'\0', ".-..-"},
    {'\0', ".-.-."},
    {'\0', ".-.--"},
    {'\0', ".--.."},
    {'\0', ".--.-"},
    {'\0', ".---."},
    {'1', ".----"},
    {'6', "-...."},
    {'\0', "-...-"},
    {'/', "-..-."},
    {'\0', "-..--"},
    {'\0', "-.-.."},
    {'\0', "-.-.-"},
    {'\0', "-.--."},
    {'\0', "-.---"},
    {'7', "--..."},
    {'\0', "--..-"},
    {'\0', "--.-."},
    {'\0', "--.--"},
    {'8', "---.."},
    {'\0', "---.-"},
    {'9', "----."},
    {'0', "-----"},
    {.last_node = 1}
};

struct node *
tree_insert(struct node *root, struct node *selnode_addr, char *string)
{
    if (string[0] == '.')
    {
        if (string[1] == 0)
        {
            return root -> left = selnode_addr;
        }
        return tree_insert(root -> left, selnode_addr, string + 1);
    }

    if (string[1] == 0)
    {
        return root -> right = selnode_addr;
    }
    return tree_insert(root -> right, selnode_addr, string + 1);
}

int
main(void)
{
    // constructs the binary tree.
    for (struct node *nodeptr = nodes + 1; !nodeptr -> last_node; nodeptr++)
    {
        tree_insert(nodes, nodeptr, nodeptr -> string);
    }

    puts("test");
    return 0;
}

在 Linux 上,它运行并打印 'test' 并通过 valgrind,没有内存错误,我在 GDB 中验证了树构建正确,但在 Windows 上它会挂起一小段时间,然后似乎崩溃了。我不知道为什么。

更新

  • 编译器是 gcc (MinGW.org GCC Build-2) 9.2.0
  • 我尝试了-std=c99 -pedantic,但也没有用。
  • Braden Best 建议删除树底部的空节点,然后它就起作用了。下面提供了新的工作树。

新数组:

static struct node nodes[] =
{
    {'\0', ""},
    {'E', "."},
    {'T', "-"},
    {'I', ".."},
    {'A', ".-"},
    {'N', "-."},
    {'M', "--"},
    {'S', "..."},
    {'U', "..-"},
    {'R', ".-."},
    {'W', ".--"},
    {'D', "-.."},
    {'K', "-.-"},
    {'G', "--."},
    {'O', "---"},
    {'H', "...."},
    {'V', "...-"},
    {'F', "..-."},
    {'\0', "..--"},
    {'L', ".-.."},
    {'P', ".--."},
    {'J', ".---"},
    {'B', "-..."},
    {'X', "-..-"},
    {'C', "-.-."},
    {'Y', "-.--"},
    {'Z', "--.."},
    {'Q', "--.-"},
    {'\0', "---."},
    {'\0', "----"},
    {'5', "....."},
    {'4', "....-"},
    {'3', "...--"},
    {'2', "..---"},
    {'1', ".----"},
    {'6', "-...."},
    {'/', "-..-."},
    {'7', "--..."},
    {'8', "---.."},
    {'9', "----."},
    {'0', "-----"},
    {.last_node = 1}
};

【问题讨论】:

  • windows 很可能没有将数组中未提及的其余字段初始化为 NULL。
  • 样式指南:点 . 和箭头 -> 运算符绑定非常紧密,因为它们是 postfix operators。它们不应该被写成周围有空格。写root -> left 不是惯用的C 语言,表示编码器是一个tyro(新手)。使用root->left
  • 有趣的是,代码中没有动态内存分配。使用预先存在的nodes 数组。因为数组是在任何函数之外定义的,所以初始化器中未明确列出的任何元素都将归零(空指针)。
  • @bruceg 你确定吗?数组是静态的。我知道 Windows 可能很糟糕,但 static 对象尤其保证默认为零。更不用说,部分定义中留空的元素保证会被清零。例如,static char array[32];char array[32] = "p"; 保证分别为 32 个零和 p 后跟 31 个零
  • 用 gcc 7.5.0-3ubuntu1~18.04 测试,-Wall -Wextra -g -Wno-missing-field-initializers,在 tree_insert 的 valgrind 中发现了一个错误。它似乎在 0x18 找到了一个地址并尝试取消引用它,即未定义的行为。有趣的是,当我第一次测试它时,我已经从树的底部删除了所有节点,让它们为空,因为我认为它们是不必要的,并且代码运行良好,没有内存错误。我让 sinan 尝试删除这些节点,这对他也有效

标签: c linux windows data-structures binary-tree


【解决方案1】:

向树中插入字符串时,您的代码假定该字符串的每个前缀都已插入。这主要是因为字符串是按长度排序的。

但是,字符串 .-.-..-.-- 被插入到树中,而它们的前缀 .-.- 从未插入。这会导致使用root == NULL 递归调用tree_insert。我很惊讶这在 Linux 上不会像我一样崩溃。

在您的固定代码中,您删除了 .-.-..-.-- 字符串,因此它可以工作。

【讨论】:

  • 哇,好收获!我帮助 OP 编写了一些代码,并告诉他按深度顺序转录每一个排列,所以我认为他已经这样做了。那里应该有一个占位符节点,而不是空指针。 root == NULL 绝对会以我写 tree_insert 的方式调用 UB。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-01
  • 2022-11-21
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多