2017-07-07 87 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])

如果你想知道指針是否指向你的程序「曾經分配過」的有效內存,你將不得不攔截分配函數,保存返回的塊指針大小,並像上例那樣進行計算。