【问题标题】:C Linked List - Create Nodes within Memory BlockC 链表 - 在内存块内创建节点
【发布时间】:2017-07-19 20:21:42
【问题描述】:

我正在尝试在预先分配的内存块中创建一个链表。简而言之,

  1. 我有一个这样声明的初始内存池。

    void *block = malloc(1000);
    
  2. 我从这个池中创建了一个链表的头部:

    struct node *root = block;
    
  3. 假设初始块的内存地址是100000。如果我添加一个大小为100的单个链表节点,这只是从100000开始(因为它是第一个节点,共享第一个的内存地址堵塞)。如果我添加第二个大小为 200 的节点,它应该从 100100 开始(在最后一个块的末尾)。下一个将从 100300 开始,以此类推。

我将节点添加到列表中的方法可以浓缩如下:

void add_node(int size) {
    new_node = malloc(sizeof(struct node));
    struct node *current = root;
    while (current != NULL) { //loop to get to the end of the linked list
        ...stuff (irrelevant to this question)...
        current = current->next;
    }
    new_node->value = size;
    current->next = new_node;
}

节点定义非常通用:

struct node {
   int value;
   int free;
   struct node *next;
};

主要方法如下:

int main(void) {
    create_block(1000);
    add_node(100);
    add_node(200);
    print_all();
}

而 print_all 只是简单地遍历并打印出内存地址:

void print_all() {
    printf("%ld (block start)\n", block);
    struct node* current = root;
    while (current != NULL) {
        printf("%ld (%d)", current->value);
        current = current->next;
    }
}

但是,当添加值为100和200的节点时,内存地址如下:

25770205072(块开始) 25770205072(100 个节点的位置 - 可以) 25769968848(200 节点的位置 - 不行。这应该是 25770205072 + 100) 25770204784(剩余 700 个内存节点的位置 - 不行。这应该是 25770205072 + 100 + 200)

我做错了什么的任何线索?我尝试了几种不同的方法,但没有任何运气。

感谢您的宝贵时间!我非常感谢任何帮助。

【问题讨论】:

  • 您没有展示如何从池中分配节点,而问题可能(应该?)出在那儿。
  • 我对帖子进行了一些编辑。这样好一点吗?
  • 您不是从池中为块分配空间,而是使用 malloc 分配新空间。您可以保留一个从根开始并按大小递增的计数器。另外,请提供您的整个代码,因为我们不知道 print_all 是做什么的。
  • 我们还需要查看结构定义。
  • 你会竭尽全力描述你自己的内存池,但从不使用它。我假设 'create_block' 设置了它,但你然后继续 malloc 你的节点。

标签: c list malloc heap-memory


【解决方案1】:

其实,这很简单。我确实使用了@Ajay Brahmakshatriya 提到的内容-“您可以保留一个从根开始并按大小递增的计数器”-并创建了一个从根开始的新长整数,并且每次都按大小递增。我没有将新节点设置为分配的新内存块,而是将其设置为旧地址 + 大小(并适当地增加了地址)。现在工作正常!谢谢!

【讨论】:

    【解决方案2】:

    警告:由于您没有显示您的池代码,这可能不是一个完整的解决方案,但add_node 有一些错误。

    你必须设置new_node->next = NULL

    在循环结束时,current 可能为 null,除非“stuff inlevant ...”保证不为 null。在这种情况下,它并非无关紧要。

    你需要一个额外的变量(例如prev

    还要注意,因为add_node 调用malloc,它绕过了你的内存池,所以你不能对地址有太多期望。

    这就是我认为你需要的[请原谅无端的风格清理]:

    void
    add_node(int size)
    {
        struct node *new_node = malloc(sizeof(struct node));
        struct node *current;
        struct node *prev;
    
        // loop to get to the end of the linked list
        prev = root;
        for (current = root;  current != NULL;  current = current->next) {
            // ... stuff(irrelevant to this question) ...
            prev = current;
        }
    
        new_node->value = size;
        new_node->next = NULL;
    
        // NOTE: this assumes root is _always_ non-null
    #if 0
        prev->next = new_node;
    #else
        if (prev != NULL)
            prev->next = new_node;
        else
            root = new_node;
    #endif
    }
    

    【讨论】:

    • 哦!这是值得赞赏的。我对 Java 最熟悉,所以你可能会看出我的一些 Java 风格流血了。
    • 不客气!顺便说一句,您所写的 printf 不正确(即您缺少第二个值)。如果您使用-Wall [您应该总是 进行编译],这将在编译时被标记。另请注意,指针通常使用%p 而不是%ld 打印,所以我会这样做:printf("%p (%d)\n",current,current->value)
    【解决方案3】:

    我只是试着记住“链表”的概念...... 它与数组不同,数组的每个元素在内存中与之前的元素完全相邻/相邻。

    我认为每个节点都是“动态分配的”。程序试图找到仍然空闲的内存,并且某个当前节点可以位于远离前一个节点的位置。但是分配给哪个节点的块大小取决于我们如何编写malloc代码,分配它的大小。

    所以我认为,您的代码没有问题..

    【讨论】:

      猜你喜欢
      • 2013-12-02
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多