c - 尽管分配了堆,但一旦函数退出,内存就会越界?

标签 c scope allocation heap-memory

一般问题:实现字典。

具体问题:根据 gdb,我的分配和一切都按预期工作。一旦使用“c”键调用 types_dict_add 就会出现问题。一切都再次按应有的方式分配,并且整个字典在整个函数上下文中都是完整的(所有指针都可以访问并且这些指针处的结构具有它们的设置值),但是一旦函数退出回到 main,mydict 指针都越界了。 mydict 中存储的实际指针地址都没有变化,但突然无法访问。在使用“c”调用之前,mydict 也是完整无缺的,因为它应该在 main.c 中

我在这里做错了什么?这真的让我感到困惑,因为我一遍又一遍地检查 gdb 并且 len 值设置正确,所以肯定有适当数量的空间被 realloc每次去。

类型.h

#ifndef _TYPES_H_
#define _TYPES_H_

union types {
    long int ival;
    char *sval;
};

struct kv {
    char* key;
    union types val;
};

struct kv    **types_dict_init();
void           types_dict_add(struct kv**, char*, union types);
struct kv     *types_dict_get(char*);
void           types_dict_free(struct kv**);

#endif

类型.c

struct kv **
types_dict_init()
{
    struct kv **newdict;

    newdict = calloc(1, sizeof(struct kv*));
    newdict[0] = NULL;

    return (newdict);
}

void
types_dict_add(struct kv** d, char* k, union types v)
{
    int len;

    if (d[0] == NULL) {
        d = realloc(d, sizeof(struct kv*) * 2);
        d[0] = malloc(sizeof(struct kv));
        d[0]->key = k;
        d[0]->val = v;
        d[1] = NULL;
    } else {
        for (len = 1; d[len - 1] != NULL; len++)
            ;
        d = realloc(d, sizeof(struct kv*) * ++len);
        d[len - 2] = malloc(sizeof(struct kv));
        d[len - 2]->key = k;
        d[len - 2]->val = v;
        d[len - 1] = NULL;
    }
}

主.c

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

#include "bencode/types.h"

int main(int argc, char **argv)
{
    struct kv **mydict;
    union types toadd;

    toadd.sval = "test";
    mydict = types_dict_init();
    types_dict_add(mydict, "a", toadd);
    types_dict_add(mydict, "b", toadd);
    types_dict_add(mydict, "c", toadd);
    types_dict_add(mydict, "d", toadd);

    for(int i = 0; i < 4; i++)
        printf("%d: %s\n", i, mydict[i]->key);

    return (EXIT_SUCCESS);
}

最佳答案

types_dict_add 中,您修改局部变量 d。此更改未反射(reflect)在 main 的变量 mydict 中,因为 C 按值传递函数参数。如果您希望 types_dict_add 能够在 mydict 上执行 realloc,则需要添加额外的间接级别。

我认为使用长度计数而不是终止 NULL 会更简单;然后你可以让你的控制结构是这样的:

struct dict
{
    struct kv **members;
    size_t n_members;
};

这也可以避免三重指针(有些人对此感到不舒服)。

关于c - 尽管分配了堆,但一旦函数退出,内存就会越界?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22876742/

相关文章:

c - 寻找优化此代码的方法

c - 随机数计算逻辑

c++ - 如何调用在 main() 内部但在外部范围内定义的变量

javascript - 为什么这段代码不起作用?

memory - Golang内存分配测试

c - led连续闪烁1秒C语言(atmega328p)

c - 如何检查单词a中单词b中的所有字符(C语言)?

java - 这样做的正确方法是什么?

C - 具有非动态元素的结构的动态分配

c++ - 我可以在超出范围后保留 vector 数据吗