简体   繁体   English

如何通过将最后一位设置为 1 来“标记”指针?

[英]How to "mark" pointers by setting the last bit to 1?

I am trying to mark and unmark pointers so I can implement Non-Blocking linked lists.我正在尝试标记和取消标记指针,以便我可以实现非阻塞链表。 I checked that on my architecture the last bit is never used, so I am trying to use change it to mark/unmark pointers.我检查了我的体系结构中最后一位从未使用过,所以我试图使用更改它来标记/取消标记指针。

I am trying to perform an OR to set the last bit to 1, an AND to unset it and an AND to check if it is set to 1. The problem is that when I perform bitwise (the commented Macros) operations on a pointer I cannot dereference it.我正在尝试执行 OR 以将最后一位设置为 1,执行 AND 以取消设置它并执行 AND 以检查它是否设置为 1。问题是当我对指针执行按位(注释的宏)操作时,我不能取消引用它。 Dereferencing it results in a segmentation fault even though the integer value of the pointer is correct.取消引用它会导致分段错误,即使指针的 integer 值是正确的。

More specifically, the #define unmark(x) (x & (uintptr_t) 0xfffffffe) is what is causing the segmentation fault.更具体地说, #define unmark(x) (x & (uintptr_t) 0xfffffffe)是导致分段错误的原因。 If I do not use it (and use #define unmark(x) x - 1 instead) the program works.如果我不使用它(而是使用#define unmark(x) x - 1 ),程序就可以运行。

Incrementing and decrementing the pointer seems to be working, but it may make the solution architecture specific.递增和递减指针似乎有效,但它可能会使解决方案体系结构变得特定。 This is because on my architecture pointers always end in 8, which has the final bit set to 0. If this is not the case my solution would not be very portable.这是因为在我的体系结构中,指针总是以 8 结尾,即最后一位设置为 0。如果不是这种情况,我的解决方案将不会很便携。

I understand that manipulating pointers is probably not portable anyway, but it is required for this algorithm.我知道操纵指针可能无论如何都不可移植,但它是该算法所必需的。 If someone knows what is causing the problem it would be fantastic.如果有人知道是什么导致了问题,那就太好了。

This is the code I have used to test the solution:这是我用来测试解决方案的代码:

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

//This produces segfault, for some reason
//#define unmark(x)     (x & (uintptr_t) 0xfffffffe)
//#define mark(x)   (x | (uintptr_t) 0x00000001)
#define is_marked(x)    ((long) x & 0x00000001)

#define mark(x)     x + 1
#define unmark(x)   x - 1

struct Example {
     long x;
     long y;
};

int main() {
    struct Example *x = malloc(sizeof(struct Example));
    x->x = 10;
    x->y = 20;
    uintptr_t p = (uintptr_t)(void*) x;

    printf("%ld\n", ((struct Example *) (void*) p)->y);

    printf("%04x\n", p);
    printf("Is marked: %d\n", is_marked(p));

    p = mark(p);
    printf("%04x\n", p);
    printf("Is marked: %d\n", is_marked(p));

    p = unmark(p);
    printf("%04x\n", p);
    printf("Is marked: %d\n", is_marked(p));

    printf("%ld\n", ((struct Example *) (void*) p)->y);

    return 0;
}

Code has many problems代码有很多问题

Not clearing just the least significant bit不清除最低有效位

x & (uintptr_t) 0xfffffffe assumes uintptr_t is 32-bit. x & (uintptr_t) 0xfffffffe假定uintptr_t是 32 位。 Better as更好的是

 #define unmark(x)  ((x) & ~(uintptr_t)1)
 // or 
 #define unmark(x)  (((x) | 1) ^ 1)

Assuming bit manipulation of pointers is OK假设指针的位操作是可以的

Mis-matched specifier不匹配的说明符

// printf("%04x\n", p);
printf("%04jx\n", (uintmax_t) p);

// printf("Is marked: %d\n", is_marked(p));
// Unclear correct specifier.

Better as更好的是

// #define is_marked(x)    ((long) x & 0x00000001)
#define is_marked(x)    (!!((x) & 1))

Unneeded casts不需要的演员表

//#define mark(x)   (x | (uintptr_t) 0x00000001)
#define mark(x)   ((x) | 1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM