473,725 Members | 2,248 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Casting to void*, result unexpected.

Hi,

I'm having a little bit of trouble regarding pointer casting in my program.
I don't understand why the following two cases produce different results.

Case 1:
IInterface *pInterface = new CImplementation ();
pInterface->Method();

Case 2:
void* pInterface = static_cast<voi d*>(new CImplementation ());
static_cast<IIn terface*>(pInte rface)->Method();

In these two cases, "IInterface " is an interface definition class, it
contains no member variables, only public pure virtual methods are defined.
"CImplementatio n" is derived from IInterface, and it implements those pure
virtual methods.

Now, if CImplementation is derived only from IInterface, the above two cases
will work the exact same way. However, when CImplementation derives from
other classes, which also contain virtual or pure virtual methods, Case 2
will fail. It'll cause a crash mainly because the ->Method() call isn't
actually calling IInterface::Met hod(), depending on the actual
inheritance, ->Method() may be pointed at a pure virtual method of another
class. Case 1 still works. Why is that? And more importantly, why is the
above two cases work differently?

Thanks,
--
He Shiming
Jul 23 '05 #1
16 2435
* He Shiming:
[unexpected result from void* casting]
...

Why is that?


Disregarding compiler-specific behavior there are only two things
you can do with a void* pointer casted from a type T: compare it wrt.
equality to another such void* pointer, and cast it back to T.

You cast to void* from a type X and then cast back to Y, and that's
Undefined Behavior even if the types X and Y are related.

Perhaps what surprises you is that static_cast can change the pointer
bitpattern (while not changing the conceptual pointer value). But if
you think about it that's how it must be. Consider:

struct A { int x; };
struct B { int y; }
struct X: A, B {};

X* pX = new X;
A* pA = static_cast<A*> ( pX );
B* pB = static_cast<B*> ( pX );

'pA' points to the beginning of the A subobject, and 'pB' points to
the beginning of the B subobject; these two pointers cannot be equal.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #2
> Disregarding compiler-specific behavior there are only two things
you can do with a void* pointer casted from a type T: compare it wrt.
equality to another such void* pointer, and cast it back to T.
You cast to void* from a type X and then cast back to Y, and that's
Undefined Behavior even if the types X and Y are related.
I'm sorry but what does this mean? I mentioned that it only fails when
multiple inheritance is used. Then if it's an undefined behavior, why does
it work flawlessly, when single inheritance is used?

Consider:

struct A { int x; };
struct B { int y; }
struct X: A, B {};

X* pX = new X;
A* pA = static_cast<A*> ( pX );
B* pB = static_cast<B*> ( pX );

'pA' points to the beginning of the A subobject, and 'pB' points to
the beginning of the B subobject; these two pointers cannot be equal.


I got your point but this isn't what exactly I wanted.

Consider case 1 in my first post, it worked with the "IInterface " type
definition on the pointer, case 2 fails because something bad happened
during pointer re-casting. The reason why I'm trying to use void* is because
I can't store the type definition in this particular case. In the first
line, the class allocator has no idea about what type should it use.

Regarding the pointer itself. Isn't the pointer just an address? Isn't void*
capable of storing any kind of pointers? If so, why won't casting work?

Thanks,
He Shiming
Jul 23 '05 #3
* "He Shiming" <mailbill(NOSPA M)@21cn.com.nos pam>:
Disregarding compiler-specific behavior there are only two things
you can do with a void* pointer casted from a type T: compare it wrt.
equality to another such void* pointer, and cast it back to T.
You cast to void* from a type X and then cast back to Y, and that's
Undefined Behavior even if the types X and Y are related.
I'm sorry but what does this mean? I mentioned that it only fails when
multiple inheritance is used. Then if it's an undefined behavior, why does
it work flawlessly, when single inheritance is used?


Undefined Behavior means the effect can be anything, including whatever you
think it "should" be.

Don't rely on Undefined Behavior.

Consider:

struct A { int x; };
struct B { int y; }
struct X: A, B {};

X* pX = new X;
A* pA = static_cast<A*> ( pX );
B* pB = static_cast<B*> ( pX );

'pA' points to the beginning of the A subobject, and 'pB' points to
the beginning of the B subobject; these two pointers cannot be equal.


I got your point but this isn't what exactly I wanted.

Consider case 1 in my first post, it worked with the "IInterface " type
definition on the pointer,


Case 1:
IInterface *pInterface = new CImplementation ();
pInterface->Method();

case 2
Case 2:
void* pInterface = static_cast<voi d*>(new CImplementation ());
static_cast<IIn terface*>(pInte rface)->Method();

fails because something bad happened during pointer re-casting.
Nope, it fails because it can. It _can_ fail because it's UB. However,
if the type you cast from is the as same the one you cast to it's no longer
UB and won't fail:

void* pInterface = static_cast<IIn terface*>( new CImplementation () );
static_cast<IIn terface*>( pInterface )->Method();

Not that I recommend such things.

Don't use void*.

The reason why I'm trying to use void* is because
I can't store the type definition in this particular case.
If you can cast the pointer back from void*, then you know the type and
don't have to use void* in the first place.

Simple.

In the first
line, the class allocator has no idea about what type should it use.
?

Regarding the pointer itself. Isn't the pointer just an address?
In general no, but for most pointers, yes.

Isn't void* capable of storing any kind of pointers?
No, but it's capable of storing the kind you're using here.

If so, why won't casting work?


Because you're casting from a type X and back to a different type Y.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #4
I'm not sure if you are aware of this. But in Microsoft COM APIs, there is
this CoCreateInstanc e function that does use void* pointer casting. The
function definition went like this:

STDAPI CoCreateInstanc e(
REFCLSID rclsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsContext,
REFIID riid,
LPVOID * ppv
);

When we use this function, we write something like this:
CComPtr<Interfa ce> spInterface;
CoCreateInstanc e(blahblahblah. ..., (void**) &spInteface) ;

CComPtr is a smart pointer, there is no void* operators defined in it. And
as you can see here, we do cast such pointers. It's pretty much what I'm
trying to do. You can see it initiates the class object to void*, and in the
smart pointer, in order to use it, it'll re-cast it back. If
CoCreateInstanc e produces a void* pointer, as you said should have undefined
behavior, and may or may not work. How are we going to use COM interfaces
correctly?

Sorry for being Microsoft-specific, but it certainly explains that it should
work.

--
He Shiming

"Alf P. Steinbach" <al***@start.no > wrote in message
news:42******** ********@news.i ndividual.net.. .
Not that I recommend such things.

Don't use void*.
If you can cast the pointer back from void*, then you know the type and
don't have to use void* in the first place.

Simple.

In the first
line, the class allocator has no idea about what type should it use.


?

Regarding the pointer itself. Isn't the pointer just an address?


In general no, but for most pointers, yes.

Isn't void* capable of storing any kind of pointers?


No, but it's capable of storing the kind you're using here.

If so, why won't casting work?


Because you're casting from a type X and back to a different type Y.

Jul 23 '05 #5
* He Shiming:
[top-posting]
Please don't top-post in this group. See the FAQ. Corrected.
* He Shiming: * Alf P. Steinbach:
* He Shiming:
..., why won't casting work?
Because you're casting from a type X and back to a different type Y.


I'm not sure if you are aware of this. But in Microsoft COM APIs, there is
this CoCreateInstanc e function that does use void* pointer casting. The
function definition went like this:

STDAPI CoCreateInstanc e(
REFCLSID rclsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsContext,
REFIID riid,
LPVOID * ppv
);


So? Ask for a pointer to the correct interface type. When the pointer
originates from type IWhatever* you can safely cast it to IWhatever*
(if you're unsure about how to specify types vis-a-vis the Microsoft
COM API, please ask about that in a Microsoft-specific group, not here).

But better, don't use void* pointers yourself.

Have I mentioned that?

...
Sorry for being Microsoft-specific, but it certainly explains that it should
work.


The example bears no relation to your "non-working" example. In that example
you casted from a type X to void*, and then back to a different type Y.
That's not the case in the example you're now giving.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #6
>* He Shiming:
[top-posting]
Please don't top-post in this group. See the FAQ. Corrected.


I don't even know how to "top-post". And how can you correct that? Just
because your Forte hates my Outlook Express doesn't justify my top-posting.


So? Ask for a pointer to the correct interface type. When the pointer
originates from type IWhatever* you can safely cast it to IWhatever*
(if you're unsure about how to specify types vis-a-vis the Microsoft
COM API, please ask about that in a Microsoft-specific group, not here).


I said sorry for being Microsoft-specific already. But if you have no idea
about how CoCreateInstanc e works, you have no idea about what I'm doing
either. FYI, CoCreateInstanc e works pretty much (although not exactly) the
same way as my Case 2 example.

"When the pointer originates from type IWhatever* you can safely cast it to
IWhatever*" <-- Well, how did you come up with that? Previously, you said
that as type B is different, one can't cast from type A to B, and then cast
from B back to A. And now you are saying that we can?

Well, given the fact the Case 2 doesn't work as expected, and I do need to
cast the specialized pointer to something general, then later cast it back.
How would you recommend a solution, or your are saying that there's no
solution at all?

Thanks,
He Shiming
Jul 23 '05 #7
You know, I got it worked.

It's as simple as this:

void* pInterface = static_cast<voi d*>(static_cast <IInterface*>(n ew
CImplementation ());

That's right, casting twice. And it also proved my point, that void* should
work, the pointer is only an address.

--
He Shiming
Jul 23 '05 #8
* "He Shiming" <mailbill(NOSPA M)@21cn.com.nos pam>:
* He Shiming:
[top-posting]
Please don't top-post in this group. See the FAQ. Corrected.


I don't even know how to "top-post". And how can you correct that? Just
because your Forte hates my Outlook Express doesn't justify my top-posting.


See the FAQ.

So? Ask for a pointer to the correct interface type. When the pointer
originates from type IWhatever* you can safely cast it to IWhatever*
(if you're unsure about how to specify types vis-a-vis the Microsoft
COM API, please ask about that in a Microsoft-specific group, not here).


I said sorry for being Microsoft-specific already. But if you have no idea
about how CoCreateInstanc e works, you have no idea about what I'm doing
either. FYI, CoCreateInstanc e works pretty much (although not exactly) the
same way as my Case 2 example.


Case 2:
void* pInterface = static_cast<voi d*>(new CImplementation ());
static_cast<IIn terface*>(pInte rface)->Method();

That's _very_ different from the OS API function: this case 2 code casts from
a type X = CImplementation * to void*, and then from void* to a different type
Y = IInterface*.

Is that unclear somehow?

Or do you believe that the OS API mentioned above does exactly that?

It doesn't: it gives you a pointer casted from the type you specify, to void*,
so simply specify the type you'll cast it back to.

"When the pointer originates from type IWhatever* you can safely cast it to
IWhatever*" <-- Well, how did you come up with that? Previously, you said
that as type B is different, one can't cast from type A to B, and then cast
from B back to A.
No, I didn't write that: I told you you get UB if you cast from A* to void*
and from that void* to B*, when A and B are different types.

And now you are saying that we can?
No, not that either.

I suggest you read the earlier postings again, with attention to detail.

Well, given the fact the Case 2 doesn't work as expected, and I do need to
cast the specialized pointer to something general, then later cast it back.
How would you recommend a solution, or your are saying that there's no
solution at all?


See above.

And the earlier replies in this thread.

The implication of those replies: figure out how to use that smart pointer
class you're using so as to avoid having void* pointers around... ;-)

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #9
Okay my bad.

--
He Shiming
"Alf P. Steinbach" <al***@start.no > wrote in message
news:42******** ********@news.i ndividual.net.. .
* "He Shiming" <mailbill(NOSPA M)@21cn.com.nos pam>:
>* He Shiming:
>> [top-posting]
>
> Please don't top-post in this group. See the FAQ. Corrected.


I don't even know how to "top-post". And how can you correct that? Just
because your Forte hates my Outlook Express doesn't justify my
top-posting.


See the FAQ.

> So? Ask for a pointer to the correct interface type. When the pointer
> originates from type IWhatever* you can safely cast it to IWhatever*
> (if you're unsure about how to specify types vis-a-vis the Microsoft
> COM API, please ask about that in a Microsoft-specific group, not
> here).
>


I said sorry for being Microsoft-specific already. But if you have no
idea
about how CoCreateInstanc e works, you have no idea about what I'm doing
either. FYI, CoCreateInstanc e works pretty much (although not exactly)
the
same way as my Case 2 example.


Case 2:
void* pInterface = static_cast<voi d*>(new CImplementation ());
static_cast<IIn terface*>(pInte rface)->Method();

That's _very_ different from the OS API function: this case 2 code casts
from
a type X = CImplementation * to void*, and then from void* to a different
type
Y = IInterface*.

Is that unclear somehow?

Or do you believe that the OS API mentioned above does exactly that?

It doesn't: it gives you a pointer casted from the type you specify, to
void*,
so simply specify the type you'll cast it back to.

"When the pointer originates from type IWhatever* you can safely cast it
to
IWhatever*" <-- Well, how did you come up with that? Previously, you said
that as type B is different, one can't cast from type A to B, and then
cast
from B back to A.


No, I didn't write that: I told you you get UB if you cast from A* to
void*
and from that void* to B*, when A and B are different types.

And now you are saying that we can?


No, not that either.

I suggest you read the earlier postings again, with attention to detail.

Well, given the fact the Case 2 doesn't work as expected, and I do need
to
cast the specialized pointer to something general, then later cast it
back.
How would you recommend a solution, or your are saying that there's no
solution at all?


See above.

And the earlier replies in this thread.

The implication of those replies: figure out how to use that smart pointer
class you're using so as to avoid having void* pointers around... ;-)

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Jul 23 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3478
by: Jacob Jensen | last post by:
This question has probably been asked a million time, but here it comes again. I want to learn the difference between the three type cast operators: static_cast, reinterpret_cast, dynamic_cast. A good way to do this is by example. So I will give an example and please tell me what you think: I have a base class A with a virtual destructor, and a class B that is it inherits publicly from A and defines som extra stuff.
231
23170
by: Brian Blais | last post by:
Hello, I saw on a couple of recent posts people saying that casting the return value of malloc is bad, like: d=(double *) malloc(50*sizeof(double)); why is this bad? I had always thought (perhaps mistakenly) that the purpose of a void pointer was to cast into a legitimate date type. Is this wrong? Why, and what is considered to be correct form?
33
2275
by: hermit_crab67 | last post by:
Can someone explain to a C newbie why this doesn't work as I expect it to work? (expectations clearly outlined in the printf statement in main routine) OS: Linux 2.4.26 GCC: 2.95.4 void modify_pointer(char *); int main(int argc, char *argv) {
35
2691
by: ytrama | last post by:
Hi, I have read in one of old posting that don't cast of pointer which is returned by the malloc. I would like to know the reason. Thanks in advance, YTR
18
2168
by: Marco | last post by:
I need to get a iterator from any generic collection. public class .... GetIterator(Object collection) { ..... }
12
13646
by: 6tc1 | last post by:
Hi all, I just discovered a rounding error that occurs in C#. I'm sure this is an old issue, but it is new to me and resulted in a fair amount of time trying to track down the issue. Basically put the following code into your C# app: float testFloat2 = (int) (4.2f * (float)100); Console.Out.WriteLine("1: "+testFloat2); and the result will be 419
33
3656
by: Mark P | last post by:
A colleague asked me something along the lines of the following today. For some type X he has: X* px = new X; Then he wants to convert px to a char* (I'm guessing for the purpose of serializing the object array). I can think of three ways to do this:
3
3652
by: Beta What | last post by:
Hello, I have a question about casting a function pointer. Say I want to make a generic module (say some ADT implementation) that requires a function pointer from the 'actual/other modules' that takes arguments of type (void *) because the ADT must be able to deal with any type of data. In my actual code, I will code the function to take arguments of their real types, then when I pass this pointer through an interface function, I...
8
9322
by: Neha | last post by:
Hi all Its seems bit silly que but pleasee explan me why this error is coming ? and what will be the solution if i want void * to be intilaize by struct * and this code is puerly in C. -- #include <stdlib.h> #include <stdio.h>
0
8889
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8752
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9401
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8099
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6702
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6011
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4784
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3228
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2157
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.