Reputation: 2510
I have N statically allocated structures.
struct exemple{
...
}
struct exemple array[N];
struct exemple *test_ptr = 0x3; /* random address */
Can I check if test_prt points to a valid address? i.e. it points to one "struct example" allocated.
Upvotes: 2
Views: 6565
Reputation: 737
I don't know if I get your question properly.
If you want to know if a pointer points to a struct of some type (cast my structs to void *
and vice-versa, for example), I do the next way:
#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;
}
It has a little bit more code because of inclusion of const-casting, but I think you get the idea.
If you want to know if test_ptr points to a aray member, you have to check this way: test_ptr >= array && test_ptr < &array[sizeof(array)/sizeof(array[0])])
. If the pointer comes from void, char, or some kind of dangerout ariyhmetic, you could also check for test_ptr % sizeof(array[0])
If you want to know if a pointer points to valid memory "ever allocated" by your program, you will have to intercept allocs functions, save returned chunks pointer & size, and compute like the previous example.
Upvotes: 0
Reputation: 12047
In general, no, you can't test if a pointer is valid or not.
But, if you want to know if a pointer points to an element of an array, you can:
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
}
This works because arrays are allocated contiguously.
Upvotes: 2
Reputation: 67476
There is no language method but in some circumstances you can try to have some known values at the certain points of the structure. If the pointed memory location has those values you can assume it as valid - but of course you do not have any guarantee. But you need to write your own functions when you create the structure, and when you destroy it (by filling with zeros before freeing the memory). It is a very week workaround - but if you connect with another measures and accept the overhead it makes the probability of the incorrect program behaviour lower.
Sometimes it is called a security cookie.
it is possible of course to make it more complicated - at certain positions you have only offsets to those cookies. It makes less probable that the random position in the memory will have such a chain of data :)
Upvotes: 0
Reputation: 7441
You can only check if pointer is valid by doing pointer != NULL
because anything except `NULL' is treated by valid pointer.
In your case, to check if your pointer points to any of your array entry, you can only do this:
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
}
But in general, you cannot just test if pointer points to specific valid location for you. It is up to you to take care of where it points. It can also have NON-NULL value but points to invalid location, for example:
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
Upvotes: 2
Reputation:
You can't. You have to know. It's not a problem if you manage your pointers correctly. A good habit is to always set pointers to 0
/ NULL
as soon as you destroy the object they point to. Then you can just test with if (ptr)
or if (!ptr)
(or, more verbose: if (ptr == NULL)
/ if (ptr != NULL)
).
Note that your last assignment
struct exemple *test_ptr = 0x3; /* random address */
is invalid. you can't assign an integer to a pointer. but you can cast it to the pointer type;
struct exemple *test_ptr = (struct exemple *)0x3; /* random address */
The result will depend on your implementation / system.
Upvotes: 5