【问题标题】:Possibly dereferencing NULL in C可能在 C 中取消引用 NULL
【发布时间】:2013-12-07 02:03:11
【问题描述】:

我正在遍历具有两个字段的节点列表:next 和 size。代码中有一点需要链接一个新节点,但我遇到了麻烦。我找到了代码段错误的地方,它看起来像这样。请注意,curr 是列表中的当前节点,我需要在 curr 和 curr->next 之间链接 temp。

    Node* temp = NULL;
    temp = ((curr + 1) + a_memory_offset_int);   //calculate the address where temp should go

    temp->next = curr->next;      //Seg faults here
    temp->size = some_other_int; //Seg faults here as well

    curr->next = temp;

有什么方法可以让我尝试为 NULL 节点设置字段吗?语法有问题吗(我相信逻辑是正确的)?

【问题讨论】:

  • 发布更多代码。并作为规则通过 valgrind 和 gdb 运行它
  • 无法在 NULL 字段中设置值。我之前的指针算法似乎有问题。请注意,它是在指针大小指针运算中进行的。
  • @BLUEPIXY 但我不认为它是 NULL,因为我将它设置为 NULL 之后的行,我将 temp 内的值更改为在前一个节点的地址之后。我明白你所说的关于指针大小的算术,这就是为什么我使用 (curr + 1) 而不是 (curr + sizeof(Node)) 的原因。感谢您的意见
  • 任何时候你都在做指针运算,你自己。我怀疑你在这里有一些误解,因为很少需要指针算术(除了通过数组递增)。
  • 不,不,A_memory_offset_int 问题的根源而不是+1?

标签: c null linked-list malloc pointer-arithmetic


【解决方案1】:

如果没有看到更多代码,我怀疑你可能不明白 a_memory_offset_int 在做什么。它的作用与+ 1 完全相同,也就是说它在做指针运算。这个:

temp = ((curr + 1) + a_memory_offset_int);

相当于:

temp = (Node*)(((char *)curr + 1*sizeof(Node)) + a_memory_offset_int*sizeof(Node));

你可能真正想要的是:

temp = (Node*)(((char *)curr + 1*sizeof(Node)) + a_memory_offset_int);

请注意,唯一的区别是a_memory_offset_int 乘以sizeof(Node)。更简单,这就是你想要的:

temp = (Node*)((char *)curr + a_memory_offset_int) + 1;

【讨论】:

  • 但是,真的,你需要发布完整的代码让我们完全理解你的意图。
  • 这行得通。我在想只有 curr + 1 受到 sizeof(Node) 的缩放因子的影响。我没有意识到整个表达式都受到了影响,包括大小的增加(这应该是不需要缩放的原始字节数)。
【解决方案2】:

链表节点的内存地址并不重要——你不应该自己计算它,而是调用 malloc,然后将其链接。

类似这样的:

Node* temp = NULL;
temp = malloc(sizeof(Node)); // create a new node, allocating fresh memor

temp->next = curr->next;     // should be fine now...
temp->size = some_other_int;

curr->next = temp;

【讨论】:

  • 这实际上是在 malloc() 的实现中,我正在调用 Mem_Alloc() 所以我不能调用 malloc,很遗憾。
  • 如果我使用 malloc() 它确实有效,但我专门实现的重点是计算内存中所有内容的地址。
  • 啊,我明白了。想到的另一件事是您的内存偏移量可能以字节为单位,但算术可能不是。 curr + 1 sill 是 Node* 类型,然后将偏移量添加到它可能会比您想象的更远地拍摄 sizeof(node) 倍。如果偏移量以字节为单位,可能有助于将它们全部转换为 unsigned char*。
  • 对,这就是我想要的。所以我们拥有的是内存中的一个块,带有一个标题和一个数据部分。标头(我们作为节点跟踪的内容)具有数据部分的大小和下一个标头的第一个字节的地址。所以 ((curr + 1) + size) 应该给我第一个字节的地址,我想在其中放置我称为 temp 的新节点。但是当我尝试更改 temp 中的字段以设置新标题时,它会出现错误。
  • 这是我为一个类似的东西写的代码:toUse->next = (Node*)((unsigned char*)(my_malloc_root + 1) + nBytes); 我把 nBytes 数了一个。所以 root + 1 移过标题。然后它被转换为 unsigned char* 所以下一个加法是字节。然后我添加字节,最后将整个内容转换回 Node* 以使警告静音。如果您的内存偏移量是四的倍数......我仍然会进行强制转换并在那里执行 offset*4 。我没有花太多时间在这上面,但这个小程序展示了我做基础的事情:arsdnet.net/test.c
【解决方案3】:

指针算法验证示例程序。

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

typedef struct node {
    int size;
    struct node * next;
} Node;

int main() {
    void *memory = malloc(10*sizeof(Node));//allocate of Node * 10
    Node *curr = memory;
    Node *temp = NULL;

    temp = curr + 1;
    temp->size = 999;
    printf("%lu\n", sizeof(Node));
    //16
    printf("%p,%p\n", (void*)curr, (void*)temp);
    //00000000004D67B0,00000000004D67C0 <- difference is 16
    int a_memory_offset_int = 16;
    temp = curr + a_memory_offset_int;
    if(temp > &curr[9])//curr[9] is last element
        printf("It is outside the allocated memory\n");//this display
    temp = curr + a_memory_offset_int/sizeof(Node);
    printf("%d\n", temp->size);//999

   return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-21
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    相关资源
    最近更新 更多