How to check if a void * pointer can be safely added to something else?

Let's say I have this function, which is part of some gui toolkit:

typedef struct _My_Struct My_Struct; /* struct ... */ void paint_handler( void* data ) { if ( IS_MY_STRUCT(data) ) /* <-- can I do something like this? */ { My_Struct* str = (My_Struct*) data; } } /* in main() */ My_Struct s; signal_connect( SIGNAL_PAINT, &paint_handler, (void*) &s ); /* sent s as a void* */ 

Since paint_handler is also called by the main contour of the GUI toolkit with other arguments, I cannot always be sure that the parameter that I get will always be a pointer to s .

Can I do something like IS_MY_STRUCT in the paint_handler function to verify that the parameter I get can safely be discarded to My_Struct* ?

+4
source share
6 answers

The void pointer loses all the information about its type, so you alone cannot check whether it can be safely discarded. A program needs to know if void* safely navigate by type.

+17
source

Unfortunately, there is no function to verify that the pointer was before it appears in this context (void).

The only solution I can think of is if you put int _struct_id as the first member of all your structures. Then this id element can be safely checked regardless of type, but it will not succeed if you pass pointers that do not implement this element (or int, char, ... pointers).

+3
source

The best thing you could do is to look at what data indicates whether it has telltale signs of what you want, although a) it will not be close to the guarantee and b) it can be dangerous since you do not know how important the evidence is. I believe this is no more dangerous than just pouring it and using it, but (as suggested) the redesign will be better.

+3
source

This is actually not the case. void pointers are faceless and need only be thrown when you really know what they are pointing to.

Perhaps you should reconsider your design; rewrite your code so that no verification is required. This is for the same reason that google forbids RTTI in the style guide .

0
source

If you create a type that is used, you can include some kind of identification information as part of the type, which will help you exclude some void pointers as being not related to the type you are looking for. Although you will be likely to have the same data or signature in some random memory area as you would, at least you would know when something was not the type you were looking for.

This approach will require that the structure be initialized so that the signature elements used to determine if the memory area is invalid are initialized with the signature value.

Example:

 typedef struct { ULONG ulSignature1; // .. data elements that you want to have ULONG ulSignature2; } MySignedStruct; #define MYSIGNEDSTRUCT_01 0x1F2E3D4C #define MYSIGNEDSTRUCT_02 0xF1E2D3C4 #define IS_MY_STRUCT(sAdr) ( (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_01 ) && (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_02)) 

This is a kind of rough approach, but it can help. Naturally, using a macro like IS_MY_STRUCT() , where the argument is used twice, can be problematic if the argument has a side effect, so you need to be careful with something like IS_MY_STRUCT(xStruct++) , where xStruct is a pointer to MySignedStruct .

0
source

I know the question is 3 years, but here I go, How about using a simple global enumeration to distinguish where the function is called from. then you can switch between what type the void pointer should indicate.

0
source

Source: https://habr.com/ru/post/1394216/


All Articles