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

前端 未结 6 2215
南旧
南旧 2020-12-19 08:32

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


        
相关标签:
6条回答
  • 2020-12-19 08:42

    The best you could do would be to look at what data points to to see if it has telltale signs of being what you want, although a) it wouldn't be anywhere close to a guarantee and b) might be dangerous, as you don't know how big the thing data actually points to is. I suppose it isn't any more dangerous than just casting it and using it, but (as has been suggested) a redesign would be better.

    0 讨论(0)
  • 2020-12-19 08:48

    Unfortunately there is no function to check what the pointer was before it appears in that context (void).

    The one solution I can think of is if you place an int _struct_id as the first member of all of your structs. This id member can then be safely checked regardless of the type but this will fail if you pass pointers that don't implement this member (or int, char, ... pointers).

    0 讨论(0)
  • 2020-12-19 08:49

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

    0 讨论(0)
  • 2020-12-19 08:50

    Your void pointer looses all its type information, so by that alone, you cannot check if it can be cast safely. It's up to the programmer to know if a void* can be cast safely to a type.

    0 讨论(0)
  • 2020-12-19 08:59

    There really isn't in c. void pointers are typeless, and should only ever be casted when you truly know what they point to.

    Perhaps you should instead reconsider your design; rewrite your code so that no inspection is necessary. This is the same reason google disallows RTTI in its style guide.

    0 讨论(0)
  • 2020-12-19 09:02

    If you are creating the type that is being used, you could include as part of the type some kind of identifying information that would help you rule out some void pointers as not being of the type you are looking for. While you would run the chance that some random area of memory would contain the same data or signature as what you are looking for, at least you would know when something was not the type you were looking for.

    This approach would require that the struct was initialized in such a way that the signature members, used to determine if the memory area is not valid, is initialized to the signature value.

    An 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 kind of a rough approach however 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 would have to be careful of something like IS_MY_STRUCT(xStruct++) where xStruct is a pointer to a MySignedStruct.

    0 讨论(0)
提交回复
热议问题