Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a void* is to a pointer on a valid instance of an object type?

I'm searching for the most common and robust way to check if a void* can be convert in a given C++ object type. You can see below some information about the context.

When I define a C API for a DLL, I often use void* to hide the C++ object I use behind (something like below)

typedef void* Instance_t;
int createInstance(Instance_t* pInst);
int processing(Instance_t inst, uint8_t* pBuf, size_t bufLength);

When I createInstance the code cast a pointer like that:

int createInstance(Instance_t* pInst)
{ 
   MyClass* ptr = new MyClass();
   *pInst = (void*)(ptr);
   //.... etc
   return 0;
 }

But the question is how can we later in all the other C function we define, check if the void* value we receive is a valid MyClass*. I think we can't as none of the C++ casting operator is really type safe is that case (even dynamic_cast).

for now my best solution is to use a C cast (or a reinterpret_cast) and if everything is ok with a call to a IsValid function define with MyClass.

Have you a better way to do that check ?

like image 318
alexbuisson Avatar asked Dec 13 '13 10:12

alexbuisson


4 Answers

You can't do that, unless you (say) allocate all your MyClass instances from a memory pool, and check the address you get passed is a pointer into to that memory pool. Or maintain a list of valid instances.

However, if you need to pass round an opaque pointer just make the client use

struct MyClass;
typedef struct MyClass *Instance_t;

This will compile cleanly and give you a reasonable amount of peace of mind. As long as you're only using the pointer, the compiler is happy. It's when it dereferences it, the compiler needs to know what the pointer actually points to.

like image 77
Tom Tanner Avatar answered Nov 15 '22 02:11

Tom Tanner


I don't think you can do this, and I don't think you should be doing this. A void * is just a pointer to some location in memory. Almost by definition, there's no way to know what it points to.

But why are you typecasting everything to void *'s, why not use protected and private methods on your class if you want to prevent users from fiddling with the internals of your class?

like image 45
craigmj Avatar answered Nov 15 '22 03:11

craigmj


There is no way to check that an untyped pointer points to a valid object of any particular type. If you use void*, you are throwing away type checking. Instead, you could declare the type in the C header, and use a pointer to that (incomplete) type rather than void*.

struct Instance;
int createInstance(struct Instance** pInst);
int processing(struct Instance* inst, uint8_t* pBuf, size_t bufLength);

Then in C++, you can define and use the class.

// Probably better to use "struct" rather than "class" in case
// some compilers complain about mixing class keys.
struct Instance {
    // Whatever
};

int createInstance(Instance** pInst) {
    *pInst = new Instance;
    // and so on
}
like image 30
Mike Seymour Avatar answered Nov 15 '22 02:11

Mike Seymour


There's no way to determine if a void* points to a valid C++ class. Unless you've got RTTI enabled then there's no metadata associated with a class, and even then there are plenty of cases in C++ where a void* isn't pointing to a class. For example:

int x=10;
void *ptr = &x;

Here ptr is pointing to a raw value. There's no RTTI associated with the integer so how could you query it to determine anything>

like image 40
Sean Avatar answered Nov 15 '22 04:11

Sean