Check if a pointer points to a valid structure - c

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.

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.

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

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.

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 :)

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.

Related

array arithmetic - pointer types indexing

In my previous question:
Pointer dereference array index I have asked about struct being dereferenced. (I will paste a snippet of code from there for recap):
#include <stdio.h>
#include <stdlib.h>
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*ar=malloc(0); //prerequisite for second case (without getting some address from OS, I cannot go 'through' *ar to (*ar+1).
//Does not matter allocation of zero bytes. (only to get some valid address)
*(ar+1) = &foo;
//(**(ar+1)).c='c'; //// first case - works
(*(*ar+1)).c='c'; //// second case - also works, with prerequisite
printf("%c\n", (*(*ar+1)).c); //prints 'c'
return 0;
}
I still do understand between pointer adding +1 in first vs second case. Well I do in the second - adding sizeof(struct Test*) to the address *ar, which like array indexing (so *ar is name pointer of array). But in the first case? what does (**(ar+1)) do? How can I add (what?) some kind of pointer type sizeof(struct Test**) when ar is not array? *(ar+1) dereference address that does not belong to me, but (*ar+1) dereference address of pointer (sizeof(struct Test*)) that DOES belong to me (an array member). So why does the first case work? (from the link, I am trying to give my understanding by resolving type being indexed [ e.g. - in first case a "step/index" is made by sizeof(struct Test**) and in second case by sizeof(struct Test*), but both have same size) - just take a look at the link.
So why does the first case work?
(**(ar+1)).c='c' doesn't work at all on my specific system.
(**(ar+1)) performs pointer arithmetic on a struct Test ** type, and (*(*ar+1)) performs pointer arithmetic on a struct Test* type.
This means that in the former case, arithmetic is done by sizeof(struct Test *) bytes, in the latter case on sizeof(struct Test) bytes.
The compiler might add padding inside your struct so that it ends up as 4 bytes etc, whatever size a pointer happens to be on your system. So they might end up at the same address by luck. Pointer sizes are commonly 2, 4 or 8 bytes, depending on if a 16, 32 or 64 bit address bus is used.
It is not very meaningful to ponder about what obscure code like this does. Explicit pointer arithmetic in general should be avoided, it is much better practice to use the [] operator to get readable code.
Also please note that malloc(0) gives "either a null pointer
is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object." If you get a null pointer and then attempt arithmetic, you have undefined behavior and anything might happen.
So let's break up your code:
Declaring a pointer to pointer to struct Test.
struct Test **ar;
Allocating space for pointers, if your system is 64 bits you are allocating space for exactly 2 contiguous pointers.
ar = malloc(16);
Allocating memory block and assigning it to the first pointer (arr[0] = malloc(0)), this is never used, but without compiler optimization you still need to initialize it, allocating 0 bytes might not be the best option since it invokes undefined behaviour but since you never store anything there it doesn't cause problems.
*ar = malloc(0);
You are storing foo address in pointer number 2, which, since it works, leads me to believe that your system is indeed 64 bits.
*(ar+1) = &foo;
Works, assigning 'c' to char c to one past the foo struct. The same as ar[0][1].c ='c';
(*(*ar+1)).c = 'c';
printf("%c\n", (*(*ar+1)).c); //prints 'c'
The out of bounds accesses work because in C one past the end of an array or allocated memory block is available, and it looks like your implementation let's you access it to write and dereference, though it's out of bounds, mine too by the way, this is not always true so you can't expect it to always work.
This all works by chance (or maybe not), because you allocate the needed space for the 2 pointers.
Now lets make some changes to you allocation to compare with what you have, and let's mess around with the structure's paddings to store and access values out of the bounds of the allocated memory.
#include <stdio.h>
#include <stdlib.h>
struct Test
{
char c;
} foo;
int main(void)
{
struct Test **ar; //declaring a pointer to pointer to struct Test
ar = malloc(sizeof(*ar) * 2); //allocation of space for 2 pointers to struct Test.
//without optimization you still need to allocate space
//or otherwise initialize the 1st pointer to avoid UB
*(ar + 0) = malloc(sizeof(**ar)); //or ar[0] = ... or *ar = ...
*(ar + 1) = &foo; //or ar[1] = ... storing foo's address in the second pointer
(*(*ar + 1)).c = 'c'; //works fine, one past the allocated memory
printf("%c\n", ar[0][1].c);
(**(ar + 1)).c = 'b'; //works, actually foo
printf("%c\n", ar[1][0].c);
(*(*(ar + 1) + 1)).c = 'a'; //also works, accessing ou of bounds
printf("%c\n", ar[1][1].c);
printf("%c\n", foo.c); //test print foo
return 0;
}
Live demo
This is much better not only in terms of readability but also in terms of portability since is the systems who decides what's the size of the pointers.
Now look at this simplified code:
#include <stdio.h>
#include <stdlib.h>
struct Test
{
char c;
} foo;
int main(void)
{
struct Test** ar;
ar = malloc(sizeof(*ar) * 2);
ar[0] = malloc(sizeof(**ar)); //or *ar = ...
ar[1] = &foo; //or *(ar + 1) = ...
ar[0]->c = 'a';
printf("%c\n", ar[0]->c);
ar[1]->c = 'c';
printf("%c\n", ar[1]->c);
printf("%c\n", foo.c); //ok foo has 'c'
return 0;
}
Look how easy it is to use double pointers if one doesn't overcomplicate things.

free struct of unions in c

I have a dynamically allocated vector of a special struct, and i trying to free but the software always crashes
the structure is :
typedef struct {
Type_e type;
union {
char m_char;
int m_int;
// more types (non of them is a pointer)
} my_data;
} Data_t;
where Type is an enum that contain all possible data types.
I allocate and initialize the vector as follows
void vector(Data_t **vec, UInt32_t start_element, UInt32_t end_element, Type_e type)
{
UInt32_t i;
Data_t *vec_ptr;
*vec=(Data_t *)malloc((size_t) ((end_element-start_element+1) * sizeof(Data_t)));
vec_ptr = *vec;
if (!vec_ptr)
{
// Write error
}
for (i =start_element; i <= end_element + 1; i++)
{
vec_ptr->type = type;
switch (type)
{
case UINT32: vec_ptr->my_data.m_int = 0; break;
// more possible cases
default:
break;
}
(vec_ptr)++;
}
}
I call this function as follows
Data_t *lVector = NULL;
vector(&lVector,0,10,INT32)
but when I try to free the allocated memory as follows,
free (lVector+start_element-1);
I tried
free (lVector+start_element);
and
free (lVector);
were start_element = 0 (in this case)
But in all cases, it crash. Am I doing anything wrong ?
This is incorrect:
*vec = *vec + sizeof(Data_t);
It advances *vec by sizeof(Data_t)*sizeof(Data_t) bytes, because pointer arithmetics multiplies integral constants by sizeof(*p) automatically.
Replace with (*vec)++, and let the compiler do the math for you. Similarly, remove multiplication in all places where you manipulate pointers. The only place in your code where you need to multiply by sizeof is when you call malloc.
Note: your code is hard to read because you move *vec back and forth as you go through the loop. You would be better off declaring and using a plain temporary pointer for iterating the vector, and keeping *vec fixed to whatever has been allocated by malloc.
You must free exactly the pointer returned by malloc, and do so exactly once. You store the return value of malloc in *vec, so free(*vec) would be correct in the same function or free(lVector) in the calling function. However, you subsequently assign other values to *vec, so to be able to free it correctly you would need to somehow restore the original return value of malloc (a better choice would almost certainly be to use another variable instead).
You also seem to misunderstand pointer arithmetic. p += n already advances the address pointed to by sizeof(*p) * n. So you mustn't multiply the changes to *vec by sizeof(Data_t) (which is sizeof(**vec)).
this parameter says array of pointers to type 'Data_t'
Data_t **vec,
however, this line:
*vec=(Data_t *)malloc((size_t) ((end_element-start_element+1) * sizeof(Data_t)));
allocates memory for an array of 'Data_t' not an array of pointers to 'Data_t'
in C, do not cast the returned value from malloc
the parameter to malloc() is automatically a 'size_t' so casting to 'size_t' just clutters the code
This line:
for (i =start_element; i <= end_element + 1; i++)
iterates over the array from index 0 to index 11 however, the valid index is from 0 to 10 as C array indexs start with 0 and end at sizeof(array) -1
this line:
(*vec)->type = type;
is expecting 'vec' to actually be an array of pointers to struct. But, as mentioned earlier, it is not
this line:
*vec = *vec + sizeof(Data_t);
is properly stepping through the array of struct However, this looses the pointer to the malloc'd memory, resulting in a memory leak because the pointer to malloc'd memory is lost so cannot be passed to free()
This line:
*vec = *vec - ((end_element-start_element+1) * sizeof(Data_t));
doesn't quite work, because the prior 'for' statement iterates one too many times.
Strongly suggest indexing off 'vec' rather than changing vec contents. I.E. vec[i]
Where do you try to call free()?
If inside vector(), you will free '&lVector', which's on the Stack and can't be freed.
You can only free space you allocated with malloc(), so you can free *vec, but not vec.

How to allocate a chunk of memory using known address in pure C, not C++

The question is in the topic name. How to allocate a memory using known address? In c++ we could use placement form of operator new(std::size_t, void* p). How can it be done in pure c?
The C++'s placement-new operator allocates the object within given address (not the memory itself), and calls its constructor.
How to allocate a memory using known address?
It is not a memory-allocation then. You either already have the memory allocated (and you know the address of a valid location), or not at all (then you don't have the address, or the address is not valid).
Assuming you already have the address of a pre-allocated memory chunk, you are already allowed to use it:
struct MyStruct { int x; };
void* my_address = ...; // known and already allocated chunk of memory, e.g.
// - from stack: char mem[sizeof(MyStruct)]; -> mem
// - from heap: malloc(sizeof(MyStruct));
// - any location that can be considered `valid'
struct MyStruct* my_struct = my_address;
my_struct->x = 1;
The correct way to use memory at a known address in C is as follows.
struct s { unsigned a; }; /* structure presumed to exist at some known location */
unsigned int loc = 0x100; /* address in known memory */
struct s* ploc = (struct s*)loc; /* cast to any pointer - see below */
s->a = 0; /* zap it */
See n1570 S6.3.2.3/7
An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
No allocation is necessary. Just use it. But don't get it wrong.
#include <stdio.h>
int main(void) {
int buffer[3] = {0};
int *address;
printf("Address of middle element is %p.\n", (void*)(buffer + 1));
printf("Enter address to assign to (try the value above +/- %d): ", (int)sizeof (int));
fflush(stdout);
scanf("%p", (void**)&address);
*address = 42;
printf("buffer contents: %d, %d, %d.\n", buffer[0], buffer[1], buffer[2]);
return 0;
}

Are "malloc(sizeof(struct a *))" and "malloc(sizeof(struct a))" the same?

This question is a continuation of Malloc call crashing, but works elsewhere
I tried the following program and I found it working (i.e. not crashing - and this was mentioned in the above mentioned link too). I May be lucky to have it working but I'm looking for a reasonable explanation from the SO experts on why this is working?!
Here are some basic understanding on allocation of memory using malloc() w.r.t structures and pointers
malloc(sizeof(struct a) * n) allocates n number of type struct a elements. And, this memory location can be stored and accessed using a pointer-to-type-"struct a". Basically a struct a *.
malloc(sizeof(struct a *) * n) allocates n number of type struct a * elements. Each element can then point to elements of type struct a. Basically malloc(sizeof(struct a *) * n) allocates an array(n-elements)-of-pointers-to-type-"struct a". And, the allocated memory location can be stored and accessed using a pointer-to-(pointer-to-"struct a"). Basically a struct a **.
So when we create an array(n-elements)-of-pointers-to-type-"struct a", is it
valid to assign that to struct a * instead of struct a ** ?
valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using pointer-to-"struct a" ?
data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
The code snippet is as follows:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
typedef struct {
int value1;
int value2;
}data;
int n = 1000;
int i;
int val=0;
data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
printf("allocation successful\n");
for (i=0 ; i<n ; i++) {
array[i].value1 = val++;
array[i].value2 = val++;
}
for (i=0 ; i<n ; i++) {
printf("%3d %3d %3d\n", i, array[i].value1, array[i].value2);
}
free(array);
printf("freeing successful\n");
return 0;
}
EDIT:
OK say if I do the following by mistake
data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
Is there a way to capture (during compile-time using any GCC flags) these kind of unintended programming typo's which could work at times and might blow out anytime! I compiled this using -Wall and found no warnings!
There seems to be a fundamental misunderstanding.
malloc(sizeof(struct a) * n) allocates n number of type struct a elements.
No, that's just what one usually does use it as after such a call. malloc(size) allocates a memory region of size bytes. What you do with that region is entirely up to you. The only thing that matters is that you don't overstep the limits of the allocated memory. Assuming 4 byte float and int and 8 byte double, after a successful malloc(100*sizeof(float));, you can use the first 120 of the 400 bytes as an array of 15 doubles, the next 120 as an array of 30 floats, then place an array of 20 chars right behind that and fill up the remaining 140 bytes with 35 ints if you wish. That's perfectly harmless defined behaviour.
malloc returns a void*, which can be implicitly cast to a pointer of any type, so
some_type **array = malloc(100 * sizeof(data *)); // intentionally unrelated types
is perfectly fine, it might just not be the amount of memory you wanted. In this case it very likely is, because pointers tend to have the same size regardless of what they're pointing to.
More likely to give you the wrong amount of memory is
data *array = malloc(n * sizeof(data*));
as you had it. If you use the allocated piece of memory as an array of n elements of type data, there are three possibilities
sizeof(data) < sizeof(data*). Then your only problem is that you're wasting some space.
sizeof(data) == sizeof(data*). Everything's fine, no space wasted, as if you had no typo at all.
sizeof(data) > sizeof(data*). Then you'll access memory you shouldn't have accessed when touching later array elements, which is undefined behaviour. Depending on various things, that could consistently work as if your code was correct, immediately crash with a segfault or anything in between (technically it could behave in a manner that cannot meaningfully be placed between those two, but that would be unusual).
If you intentionally do that, knowing point 1. or 2. applies, it's bad practice, but not an error. If you do it unintentionally, it is an error regardless of which point applies, harmless but hard to find while 1. or 2. applies, harmful but normally easier to detect in case of 3.
In your examples. data was 4 resp. 8 bytes (probably), which on a 64-bit system puts them into 1. resp. 2. with high probability, on a 32-bit system into 2 resp. 3.
The recommended way to avoid such errors is to
type *pointer = malloc(num_elems * sizeof(*pointer));
No.
sizeof(struct a*) is the size of a pointer.
sizeof(struct a) is the size of the entire struct.
This array = (data *)malloc(sizeof(data *) * n) allocates a sizeof(data*) (pointer) to struct data, if you want to do that, you need a your array to be a data** array.
In your case you want your pointer to point to sizeof(data), a structure in memory, not to another pointer. That would require a data** (pointer to pointer).
is it valid to assign that to struct a * instead of struct a ** ?
Well, technically speaking, it is valid to assign like that, but it is wrong (UB) to dereference such pointer. You don't want to do this.
valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using pointer-to-"struct a" ?
No, undefined behavior.

Basic question: C function to return pointer to malloc'ed struct

About C structs and pointers...
Yesterday I wrote sort of the following code (try to memorize parts of it out of my memory):
typedef struct {
unsigned short int iFrames;
unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
} Tile;
Tile* loadTile(char* sFile)
{
// expecting to declare enough space for one complete Tile structure, of which the base memory address is stored in the tmpResult pointer
Tile* tmpResult = malloc(sizeof(Tile));
// do things that set values to the Tile entity
// ...
// return the pointer for further use
return tmpResult;
}
void main()
{
// define a tile pointer and set its value to the returned pointer (this should also be allowed in one row)
// Expected to receive the VALUE of the pointer - i.e. the base memory address at where malloc made space available
Tile* tmpTile;
tmpTile = loadTile("tile1.dat");
// get/set elements of the tile
// ...
// free the tile
free(tmpTile);
}
What I see: I cán use the malloced Tile structure inside the function, but once I try to access it in Main, I get an error from Visual Studio about the heap (which tells me that something is freed after the call is returned).
If I change it so that I malloc space in Main, and pass the pointer to this space to the loadTile function as an argument (so that the function does no longer return anything) then it does work but I am confident that I should also be able do let the loadTile function malloc the space and return a pointer to that space right?!
Thanks!!
There's nothing wrong with what you're trying to do, or at least not from the code here. However, I'm concerned about this line:
unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
That isn't true unless you're also mallocing iTime somewhere:
Tile* tmpResult = malloc(sizeof(Tile));
tmpResult->iTime = malloc(sizeof(short) * n);
You will need to free it when you clean up:
free(tmpTile->iTime);
free(tmpTile);
You are probably writing over memory you don't own. I guess that in this section:
// do things that set values to the Tile entity
you're doing this:
tmpResult->iFrames = n;
for (i = 0 ; i < n ; ++n)
{
tmpResult->iTime [i] = <some value>;
}
which is wrong, you need to allocate separate memory for the array:
tmpResult->iTime = malloc (sizeof (short int) * n);
before writing to it. This make freeing the object more complex:
free (tile->iTime);
free (tile);
Alternatively, do this:
typedef struct {
unsigned short int iFrames;
unsigned short int iTime [1]; // array with elements [0..x] holding the timing for each frame
} Tile;
and malloc like this:
tile = malloc (sizeof (Tile) + sizeof (short int) * (n - 1)); // -1 since Tile already has one int defined.
and the for loop remains the same:
for (i = 0 ; i < n ; ++n)
{
tmpResult->iTime [i] = <some value>;
}
but freeing the tile is then just:
free (tile);
as you've only allocated one chunk of memory, not two. This works because C (and C++) does not do range checking on arrays.
You code, with as little changes as I could live with, works for me:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned short int iFrames;
unsigned short int* iTime;
} Tile;
Tile *loadTile(char* sFile) {
Tile *tmpResult = malloc(sizeof *tmpResult);
if (!tmpResult) return NULL;
/* do things that set values to the Tile entity */
/* note that iTime is uninitialized */
tmpResult->iFrames = 42;
(void)sFile; /* used parameter */
return tmpResult;
}
int main(void) {
Tile* tmpTile;
tmpTile = loadTile("tile1.dat");
if (!tmpTile) return 1;
printf("value: %d\n", tmpTile->iFrames);
free(tmpTile);
return 0;
}
The code you showed looks OK, the error must be in the elided code.
Whatever problem you are having, it is not in the code shown in this question. Make sure you are not clobbering the pointer before returning it.
This should work fine... could just be a warning from VisualStudio that you are freeing a pointer in a different function than it was malloced in.
Technically, your code will work on a C compiler. However, allocating dynamically inside functions and returning pointers to the allocated data is an excellent way of creating memory leaks - therefore it is very bad programming practice. A better way is to allocate the memory in the caller (main in this case). The code unit allocating the memory should be the same one that frees it.
Btw if this is a Windows program, main() must be declared to return int, or the code will not compile on a C compiler.

Resources