2017-07-07 39 views
1

我有N个静态分配的结构。检查指针是否指向有效结构

struct exemple{ 
    ... 
} 

struct exemple array[N]; 
struct exemple *test_ptr = 0x3; /* random address */ 

我可以检查test_prt是否指向有效地址?即它指向分配的一个“结构示例”。

回答

2

只能通过执行pointer != NULL来检查指针是否有效,因为除NULL之外的任何内容均被有效指针处理。

你的情况,检查你的指针指向任何你数组项,你只能做到这一点:

size_t i = 0; 
int isValid = 0; 
for (i = 0; i < N; i++) { 
    if (test_ptr == &array[i]) { 
     isValid = 1; 
     break; 
    } 
} 

if (isValid) { 
    //Pointer points to one of your array entry 
} 

但在一般情况下,你不能只是指针指向测试特定的有效位置您。由你来负责照顾它所指的地方。它也可以有非空值,但指向无效的位置,例如:

int* ptr = malloc(10); //Now points to allocated memory 
*ptr = 10; 
free(ptr); //Free memory 
*ptr = 10; //Undefined behaviour, it still points to the same address but 
      //we don't know what will happen. Depends on implementation 
+0

我知道我可以做阵列检查,但我想知道是否有更多的直接方法。谢谢 – alessiovolpe

+0

@alessiovolpe不幸的是,没有,这就是为什么C是控制语言:) – tilz0R

+0

这对于大型阵列来说效率非常低。 **有更直接的方式,@alessiovolpe。 – alain

5

你不能。你必须知道。如果你正确地管理你的指针,这不是一个问题。一个好习惯就是一旦销毁它们指向的对象,就总是设置指向0/NULL的指针。然后,您可以仅使用if (ptr)if (!ptr)(或更详细:if (ptr == NULL)/if (ptr != NULL))进行测试。

需要注意的是你的最后分配

struct exemple *test_ptr = 0x3; /* random address */ 

无效。你不能给一个指针赋一个整数。但你可以它的指针类型;

struct exemple *test_ptr = (struct exemple *)0x3; /* random address */ 

结果将取决于您的实施/系统。

0

没有语言方法,但在某些情况下,您可以尝试在结构的某些点处具有一些已知值。如果指向的内存位置具有这些值,则可以将其视为有效 - 但当然,您没有任何担保。但是当你创建结构时,你需要编写自己的函数,以及何时将其销毁(通过在释放内存之前填充零)。这是一个非常周的解决方法 - 但是如果你连接另一个度量并接受开销,它会降低不正确的程序行为的概率。

有时它被称为安全cookie。

当然有可能使它变得更加复杂 - 在某些位置上,只有这些饼干有偏移量。它使内存中的随机位置不太可能具有这样的数据链:)

1

一般来说,不,你不能测试指针是否有效。

但是,如果你想知道,如果一个指针指向一个数组的元素,您可以:

if(test_ptr >= &array[0] && test_ptr < &array[N] 
     && ((intptr_t)test_ptr - (intptr_t)array)%((intptr_t)(&array[1]) - (intptr_t)array) == 0) { 
    // test_ptr points to an element of array 
} 

这工作,因为数组连续地分配。

+1

这在任何情况下都不起作用。如果你想要你的方法,你必须首先减去:'((intptr_t)test_ptr - (intptr_t)&array [0])%sizeof ...''''''更好的方法是使用'test_ptr <=&array [N-1]' 。所以,你的方法目前是*未定义行为*。 – tilz0R

+0

感谢您指出缺少的减法@ tilz0R。但是不需要使用'array [N-1]',因为可以指向数组的一个末尾而不会导致UB。 – alain

+0

是的,同意你的看法。 – tilz0R

0

我不知道我是否正确地得到您的问题。

如果你想知道,如果一个指针指向某种类型的结构(投我的结构,以void *,反之亦然,例如),我做了下道:

#include <assert.h> 
struct my_struct { 
#ifndef NDEBUG 
#define MY_STRUCT_MAGIC 0x1234abcd 
    uint64_t magic; 
#endif 
    int my_data; 
}; 

void init_struct(struct my_struct *s, int t_data) { 
#ifdef MY_STRUCT_MAGIC 
    s->magic = MY_STRUCT_MAGIC; 
#endif 
    s->my_data = t_data; 
} 

my_struct *my_struct_cast(void *vs) { 
    my_struct *s = vs; 
#ifdef MY_STRUCT_MAGIC 
    assert(MY_STRUCT_MAGIC == s->magic); 
#endif 
    return s; 
} 

它有一个由于包含了const-casting,所以代码更多一点,但我认为你明白了。


如果你想知道,如果test_ptr指向阿雷成员,你必须检查这种方式:test_ptr >= array && test_ptr < &array[sizeof(array)/sizeof(array[0])])。如果指针来自void,char或者某种危险的ariyhmetic,那么你也可以检查test_ptr % sizeof(array[0])

如果你想知道指针是否指向你的程序“曾经分配过”的有效内存,你将不得不拦截分配函数,保存返回的块指针大小,并像上例那样进行计算。