【问题标题】:Different behaviour for malloc(sizeof(struct Node)) vs malloc(sizeof(nodeptr))malloc(sizeof(struct Node)) 与 malloc(sizeof(nodeptr)) 的不同行为
【发布时间】:2019-11-23 17:30:09
【问题描述】:

我试图使用 malloc 分配内存,但我无法理解为什么这两个 malloc 调用得到不同的结果。

下面的行给了我错误的结果,即使使用 gdb 我看到了 数据被分配了正确的值。

  • nodeptr n = malloc(sizeof(nodeptr));

    值头->数据:'!'
    值 head->eq->data: ''

当我这样做时得到正确的结果:

  • nodeptr n = malloc(sizeof(struct Node));

    值头->数据:'w'
    值 head->eq->data: 'X'

我关注了this 的帖子,我认为我做得对。
在这两种方式中,虽然分配的内存量相同,但我最终看到的结果不同。强>

typedef struct Node
{
    struct Node *left, *right, *eq;
    char data;
    bool isEnd;
} *nodeptr;

nodeptr newNode(const char c) {
    nodeptr n = malloc(sizeof(nodeptr));
    // nodeptr n = malloc(sizeof(struct Node));
    n->data = c;
    n->left = NULL;
    n->right = NULL;
    n->left = NULL;
    n->isEnd = false;

    return n;
}

void insert(nodeptr *node, const char *str) {

    if (*node == NULL) {
        *node = newNode(*str);
    }
    nodeptr pCrawl = *node;

    if(pCrawl->data < *str) {
        insert(&pCrawl->right, str);
    } else if (pCrawl->data > *str) {
        insert(&pCrawl->left, str);
    } else {
        if(*(str+1)) {
            insert(&pCrawl->eq, str + 1);
        } else {
            pCrawl->isEnd = true;
        }
    }
}

int main(int argc, char const *argv[])
{

    const char* const strs[5]= {
        "w.",
    };
    nodeptr head = NULL;
    for(int i = 0; i<1; i++) {
        insert(&head, strs[i]);
    }
    return 0;
    printf("Value head->data: \'%c\'\n", head->data);
    printf("Value head->eq->data: \'%c\'\n", head->eq->data);
}

【问题讨论】:

  • 请注意newNode() 函数不会初始化结构的eq 成员。它应该。
  • 关于; nodeptr n = malloc(sizeof(nodeptr)); 这将为指针分配足够的内存。 (4 或 8 个字节,取决于底层硬件和某些编译器选项)因此,将任何内容写为该指针的偏移量都是未定义的行为。
  • OT:不要通过typedefs 隐藏指针

标签: c pointers struct tree


【解决方案1】:

sizeof(nodeptr) == sizeof(struct Node*) != sizeof(struct Node) == sizeof(*nodeptr)

  • sizeof(nodeptr) 将始终是指针的大小(如 64 位 CPU 上的 8 个字节)
  • sizeof(struct Node) 指的是结构体内容
  • sizeof(*nodeptr) 等价于 sizeof(struct Node),其中包含额外的取消引用运算符。

它可能看起来“工作”(不是段错误)的原因是malloc 从更大的堆内存块进行子分配。但是,代码超出了请求分配的范围,这最终会在某些时候导致堆损坏或段错误。

【讨论】:

    【解决方案2】:

    两个不同的版本分配的内存量不同。 sizeof(nodeptr) 是 指针 的大小,sizeof(struct Node) 是 struct 的大小。这些不是相同的东西,它们的大小也不同。在我的计算机上,这些值为 8 和 32。

    你想使用:

    nodeptr n = malloc(sizeof(struct Node));
    

    或许:

    nodeptr n = malloc(sizeof(*n)); // size of the type that n points too
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-26
      • 2013-02-19
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多