• Advertisement
Sign in to follow this  

64bit - point to int cast

This topic is 4169 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i've just written some code: where nextInstance is a void* instance is a void* int* ptr = (int*)((char*)instance + variableInfo->offset); *ptr = (int)nextInstance; as soon as i finished these 2 lines of code i went, OMG this probably isnt 64bit safe, so what is the safe way to do this? unfortunately i have to cast it to a non void* as: something like the following: void* ptr = (void*)((char*)instance + variableInfo->offset); *ptr = nextInstance does not compile any ideas on making this safe?

Share this post


Link to post
Share on other sites
Advertisement
It might be helpful to know where you get nextInstance from (and why it's a pointer)

Basically, you should just try to keep your usage of the two types separate. pointers are for representing addresses. ints are for representing integer data values. If nextInstance is data you need, then it should be an int to begin with. If it's meant to contain an address, it should be a pointer all along.

At least that's what you should aim for. Since we don't know why nextInstance is a pointer in your case, it's hard to offer more advice than that.

Share this post


Link to post
Share on other sites
instance is a pointer to some arbitary class, while nextInstance is also a pointer to some data, that needs to be poked in to instance at a certain offset (ie poked in to a pointer variable of instance) obvisouly instance is an unknown class, but the offset to the pointer variable is known

Share this post


Link to post
Share on other sites
You are trying to solve a problem that seems to have been created by Really Bad Programming... Having to access an attribute in that way should never happen, and I don't think that there really is a safe way to do it.

If you know that (char*)instance + variableInfo->offset points to a pointer variable (which is actually the hard part), then you can safely write any pointer that is not a function pointer to that address. (It is not guaranteed that a function pointer fits into a void pointer. It will work on most systems, but it doesn't have to.)

From that point of view, you first try was close.

// the offset must be correct
int** ptr = (int**)((char*)instance + variableInfo->offset);
// now *ptr resolves to an int* variable
*ptr = (int*)nextInstance;

Share this post


Link to post
Share on other sites
Quote:
Original post by supagu
i've just written some code:

where nextInstance is a void*
instance is a void*

any ideas on making this safe?


The first thing I'd suggest is to forget you ever heard that there was such a thing as a void*.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by supagu
i've just written some code:

where nextInstance is a void*
instance is a void*

any ideas on making this safe?


The first thing I'd suggest is to forget you ever heard that there was such a thing as a void*.

What's a "void*"?

@supagu: store pointers in pointers. Their size may vary, and may be different from the size of an integer. The future C++0x standard might define an intptr_t type that would ease such manipulation, and you can do the same (either as a typedef or as a class - in order to ensure type safety).

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by Shadowdancer
It is not guaranteed that a function pointer fits into a void pointer. It will work on most systems, but it doesn't have to


huh? What possible reason could there be for that?

Share this post


Link to post
Share on other sites
Quote:
Original post by DaBookshah
Quote:
Original post by Shadowdancer
It is not guaranteed that a function pointer fits into a void pointer. It will work on most systems, but it doesn't have to


huh? What possible reason could there be for that?


All pointers have the same size - including function pointers. You can safely promote a void* to a function pointer (the opposite is true too). If your compiler doesn't allow you to do this, report this as a bug to the compiler vendor. See sections 4.3 [conv.func] and 4.10§2 [conv.ptr] of the C++ standard.

I think you wanted to speak about member function pointers. They are still pointers, but they carry more information, making it impossible to convert them to a void* (or to any pointer type). However, this has nothing to do with the pointer size.

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by supagu
any ideas on making this safe?


Any code that converts pointers everywhichway, including through char* and void*, cannot be safe. You might be able to make it less-unsafe by adding comments about what your intent is, what preconditions and postconditions are expected, and generally why no other safer, non-pointer-crazy method could not achieve the same thing.

As far as I am concerned, I would stick with:


// Allow changing the implementation of a "Location" class
// instead of using a naked reference.
template<typename Data> class Location {
Data & data;
public:
Location(Data& data) : data(data) {}
void Insert(Data& inserted) { this->data = inserted; }
};

// An example class, used to insert data at a given location.
class Pokeable {
int* memberVariable;
public:
Location<int*> GetPokeLocation() {
return Location(this->memberVariable);
}
};

// Do the poking.
void DoPoke(int* nextInstance, Pokeable& instance) {
instance.GetPokeLocation().Insert(nextInstance);
}

// Do the poking on an arbitrary class:
template<typename Data, typename Class)
void DoArbitraryPoke(Data nextInstance, Class& instance) {
instance.GetPokeLocation().Insert(nextInstance);
}

// Better poking on arbitrary class: forget about the
// class and pass the Location around.
void DoArbitraryPoke2(int* nextInstance, Location<int*> where) {
where.Insert(nextInstance);
}




The design is still ugly as hell, but at least it's safe.

Share this post


Link to post
Share on other sites
Quote:
Original post by supagu
i've just written some code:

where nextInstance is a void*
instance is a void*

int* ptr = (int*)((char*)instance + variableInfo->offset);
*ptr = (int)nextInstance;

...


Just my 2cent ...

On an 64-bit Alpha int is 32 bit and Pointers are 64 bit ...
so the seconde line of code does not look save in the situation.

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
I think you wanted to speak about member function pointers. They are still pointers, but they carry more information, making it impossible to convert them to a void* (or to any pointer type). However, this has nothing to do with the pointer size.


I am talking about this, referenced from here.

Share this post


Link to post
Share on other sites
Quote:
From this link:
The fact that C++ compilers are required to issue a diagnostic [while C compilers can allow undefined behavior] is viewed as a "competitive disadvantage" for the language.


I don't know whether to laugh or cry. As for the void* conversion issue on function pointers, 4.10§2 states:

Quote:
The Holy Standard, 4.10§2:
An rvalue of type ``pointer to cv T,'' where T is an object type, can be converted to an rvalue of type ``pointer to cv void.''


Emphasis mine.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
From this link:
The fact that C++ compilers are required to issue a diagnostic [while C compilers can allow undefined behavior] is viewed as a "competitive disadvantage" for the language.


I don't know whether to laugh or cry. As for the void* conversion issue on function pointers, 4.10§2 states:

Quote:
The Holy Standard, 4.10§2:
An rvalue of type ``pointer to cv T,'' where T is an object type, can be converted to an rvalue of type ``pointer to cv void.''


Emphasis mine.


Rumble rumble rumble. The Holy One makes a difference between pointers to functions and pointers to object type. Rumble rumble rumble.

They really thought that there is a computer architecture where data and code are not using the same addressing mecanism? (although this can be designed on paper, it would require a fairly strange and utterly innefective hardware architecture).

So far, sorry for my misleading post.

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
They really thought that there is a computer architecture where data and code are not using the same addressing mecanism? (although this can be designed on paper, it would require a fairly strange and utterly innefective hardware architecture).


Yeah, I'd also be interested in seeing such a beast. I could imagine that one of the more exotic supercomputer architectures in the past could indeed have suffered from that, but today's systems shouldn't have that problem.

I should have pointed out explicitly that this is likely a very exotic problem that one is very unlikely to encounter.

Share this post


Link to post
Share on other sites
Quote:
Original post by Shadowdancer
Quote:
Original post by Emmanuel Deloget
They really thought that there is a computer architecture where data and code are not using the same addressing mecanism? (although this can be designed on paper, it would require a fairly strange and utterly innefective hardware architecture).


Yeah, I'd also be interested in seeing such a beast. I could imagine that one of the more exotic supercomputer architectures in the past could indeed have suffered from that, but today's systems shouldn't have that problem.

I should have pointed out explicitly that this is likely a very exotic problem that one is very unlikely to encounter.


Harvard architecture processors like the microchip pic line work exactly like that. Not that I've seen a c++ compiler for those, but I suppose someone could write one.


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by cavemanbob
Quote:
Original post by Shadowdancer
Quote:
Original post by Emmanuel Deloget
They really thought that there is a computer architecture where data and code are not using the same addressing mecanism? (although this can be designed on paper, it would require a fairly strange and utterly innefective hardware architecture).


Yeah, I'd also be interested in seeing such a beast. I could imagine that one of the more exotic supercomputer architectures in the past could indeed have suffered from that, but today's systems shouldn't have that problem.

I should have pointed out explicitly that this is likely a very exotic problem that one is very unlikely to encounter.


Harvard architecture processors like the microchip pic line work exactly like that. Not that I've seen a c++ compiler for those, but I suppose someone could write one.


There is one, although it produces very big and slow code compared to hand written assembly. The same behaviour can be seen on some older macos systems, where the compiler used extra code to link in libraries. The hitachi (now renesas) micro line is also known to contain very strange addressing modes. Not everything is x86 or ppc. (and yes, on the intel itanium, sizeof(int) != sizeof(void*) != sizeof(long long))

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
They really thought that there is a computer architecture where data and code are not using the same addressing mecanism? (although this can be designed on paper, it would require a fairly strange and utterly innefective hardware architecture).


The venerable Intel 386 is such a beast.

Oh, yes, as used by the Windows family of operating systems you won't see such behaviour, but it's quite possible to set the flags in a segment descriptor so that you cannot execute code contained in a memory page.

So, while a pointer-to-function and a pointer-to-object may be of the same number of bits and conceivably occupy the same storage, they point to two things that are not convertable. By requiring diagnostics from the compiler you are forced to either explicitly do something unsafe (store executable code in the data region, AKA exploit i pwnxxor u) or design your code more safely.

Other historic architectures: the TI 99/4A computer stored its software in video memory, not CPU RAM. Granted, it would be difficult to link C++ code to tokenized TI-BASIC, but again, the functions were stored in an entirely different address space than data were.

Share this post


Link to post
Share on other sites
Quote:
Original post by supagu
instance is a pointer to some arbitary class, while nextInstance is also a pointer to some data, that needs to be poked in to instance at a certain offset (ie poked in to a pointer variable of instance) obvisouly instance is an unknown class, but the offset to the pointer variable is known
It sounds as though the last thing you did was programming in basic on a commodore 64 or something.[smile]
You don't use the terms "poke", "poking", or "poked" in C++.

Share this post


Link to post
Share on other sites
First, some good articles to read are:
64-bit programming for Game Developers (MSDN)
Rules for Using Pointers (MSDN)

Quote:
Original post by supagu
any ideas on making this safe?


I agree that you should avoid void* (hehe) if you want safety in general. But if you just want to store a pointer in an int, you can probably use intptr_t, uintptr_t (as mentioned already). The MS compilers support it already. There's also ptrdiff_t, if you want.

(reference: MSDN )

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement