Q: address of operator new/delete

J

Jakob Bieling

Hi,

is it possible to get the address of operator new/delete and operator
new[]/delete[] portably? Otherwise I would have to go for a non-portable and
rather unclean solution.

Thanks for any hints!
 
R

Ron Natalie

Jakob Bieling said:
Hi,

is it possible to get the address of operator new/delete and operator
new[]/delete[] portably? Otherwise I would have to go for a non-portable and
rather unclean solution.

#include <new>

using namespace std;

int main() {
void* (*ona)(size_t) = &operator new[];
}
 
J

Jakob Bieling

Ron Natalie said:
Hi,

is it possible to get the address of operator new/delete and operator
new[]/delete[] portably? Otherwise I would have to go for a non-portable and
rather unclean solution.

#include <new>

using namespace std;

int main() {
void* (*ona)(size_t) = &operator new[];
}


Oh I see. I tried to convert it to a void* directly and I prolly did not
know which overloaded operator's address I wanted. With a static_cast it
works now.

Thanks!
 
T

tom_usenet

Hi,

is it possible to get the address of operator new/delete and operator
new[]/delete[] portably? Otherwise I would have to go for a non-portable and
rather unclean solution.

AFAIK, this is fine and portable:

#include <cstddef>
#include <new>

struct A
{
void* operator new(size_t)
{
throw std::bad_alloc();
}
};

int main()
{
void* (*ptr1)(std::size_t) = ::eek:perator new;
void* (*ptr2)(std::size_t) = &A::eek:perator new;
}

Tom
 
R

Ron Natalie

Jakob Bieling said:
Oh I see. I tried to convert it to a void* directly and I prolly did not
know which overloaded operator's address I wanted. With a static_cast it
works now.

You can't convert it to void* portably at all. void* is only guaranteed to be
able to hold pointers to (data) objects. You need to use some sort of function
pointer (even if you must cast it) to hold a function pointer.
 
J

Jakob Bieling

Ron Natalie said:
You can't convert it to void* portably at all. void* is only guaranteed to be
able to hold pointers to (data) objects. You need to use some sort of function
pointer (even if you must cast it) to hold a function pointer.


Well, I was not going to cast it back for use. I just wanted to store
the address to be able to print it out and void* seemed somewhat
appropriate. What else would you suggest?

regards
 
J

Jakob Bieling

I tried to convert it to a void* directly and I prolly did not
know which overloaded operator's address I wanted.


Little typo there btw. I meant to say "[..] and it prolly did not know
which overloaded operator's address I wanted".
 
T

tom_usenet

Well, I was not going to cast it back for use. I just wanted to store
the address to be able to print it out and void* seemed somewhat
appropriate. What else would you suggest?

It is legal to reinterpret_cast to a sufficiently large integer type -
I'd recommend unsigned long.

Compilers are required to issue a diagnostic if you cast a function
pointer to an object pointer, although there is a defect report
exploring this issue:

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#195

Tom
 
G

Gianni Mariani

tom_usenet said:
It is legal to reinterpret_cast to a sufficiently large integer type -
I'd recommend unsigned long.

Do you think that ptr_diff_t is more appropriate than unsigned long ?
 
A

Andrey Tarasevich

Jakob said:
...
is it possible to get the address of operator new/delete and operator
new[]/delete[] portably? Otherwise I would have to go for a non-portable and
rather unclean solution.
...

It is possible, as others already stated. But keep in mind that the
functionality of functions 'operator new/delete' contains only a portion
of functionality of a new/delete expression (for class types with
non-trivial construction and destruction at least). If you want to
create a pointer to something that would reproduce the complete
functionality of new/delete expression, you'll have to write a dedicated
wrapper function (or use a library that provides one).
 
R

Ron Natalie

Jakob Bieling said:
Well, I was not going to cast it back for use. I just wanted to store
the address to be able to print it out and void* seemed somewhat
appropriate. What else would you suggest?

There's no guarantee it will fit. I'd just use the void * (*)() type I
suggested before and cast it to a large integer and hope that's good
enough.
 
R

Ron Natalie

Gianni Mariani said:
Do you think that ptr_diff_t is more appropriate than unsigned long ?
ptr_diff_t isn't necessarily the right answer. All that has to be is big
enough to hold the difference in offsets in the largest allocatable
array and still that's object sizes not code sizes. size_t is almost
certainly as big or bigger than ptr_diff_t, but it's still no guarantee.
 
J

Jakob Bieling

Andrey Tarasevich said:
Jakob said:
...
is it possible to get the address of operator new/delete and operator
new[]/delete[] portably? Otherwise I would have to go for a non-portable and
rather unclean solution.
...

It is possible, as others already stated. But keep in mind that the
functionality of functions 'operator new/delete' contains only a portion
of functionality of a new/delete expression (for class types with
non-trivial construction and destruction at least). If you want to
create a pointer to something that would reproduce the complete
functionality of new/delete expression, you'll have to write a dedicated
wrapper function (or use a library that provides one).


I already replied to Tom's message, that the pointers will not be used
to call the functions. What I meant is, I solely want to be able to uniquely
identify functions, and their addresses are the perfect id. Instead of
having them stored in pointers, I just want the numerical value. Looks like
I will store them in a size_t or unsigned long by using a cast.

Thanks
 
G

Gianni Mariani

Ron said:
ptr_diff_t isn't necessarily the right answer. All that has to be is big
enough to hold the difference in offsets in the largest allocatable
array and still that's object sizes not code sizes. size_t is almost
certainly as big or bigger than ptr_diff_t, but it's still no guarantee.

Where is the definition ?

So this code is undefined ? (a little contrived ...)

int main()
{

char foo[ 1 ];

ptr_diff_t x = foo - ( char * ) 0;

char * foo_ptr = x + ( char * ) 0;

return foo == foo_ptr;
}
 
R

Ron Natalie

Gianni Mariani said:
So this code is undefined ? (a little contrived ...)
char foo[ 1 ];

ptr_diff_t x = foo - ( char * ) 0;

Aboslutely. You can only compare between two pointer values that
point into the same array.
char * foo_ptr = x + ( char * ) 0;
This doesn't even compile. You can't add pointers.
 
L

llewelly

It is legal to reinterpret_cast to a sufficiently large integer type -
I'd recommend unsigned long.
[snip]

But why, when storing it in a void(*)() is guaranteed safe? There are
platforms (rather, compiler flag sets on 64bit platforms) on which
code pointers are 64 bit, but unsigned long is only 32.
 
R

Ron Natalie

llewelly said:
But why, when storing it in a void(*)() is guaranteed safe? There are
platforms (rather, compiler flag sets on 64bit platforms) on which
code pointers are 64 bit, but unsigned long is only 32.

Because void(*)() would have to be a 64-bit type. The standard doesn't
guarantee that there is any integral type that is big enough to hold a function
pointer, but says that if there is one, you can convert back and forth to it
without information loss.
 
G

Gianni Mariani

Ron said:
So this code is undefined ? (a little contrived ...)

char foo[ 1 ];

ptr_diff_t x = foo - ( char * ) 0;
it's ptrdiff_t ...
Aboslutely. You can only compare between two pointer values that
point into the same array.

I have this humungous char array that starts from ( char * ) 0 ...
This doesn't even compile. You can't add pointers.

ptrdiff_t in an integral type - you can add them to pointers as much as
you like.

This compiles for me on GCC 3.3.1 and MSVC 6.0.

#include <cstddef>

int main()
{

char foo[ 1 ];

ptrdiff_t x = foo - ( char * ) 0;

char * foo_ptr = x + ( char * ) 0;

return foo == foo_ptr;
}


It's been a very long time but from what I remember, ptrdiff_t is
supposed to guarentee that it is able to hold a pointer. It becomes
somewhat difficult to write memory allocators it this is not true.

On a machine with 64 bit pointers ptrdiff_t is a 64 bit integer type.

It would make very little sense to be otherwise.
 
R

Ron Natalie

Gianni Mariani said:
I have this humungous char array that starts from ( char * ) 0 ...

No you do not. There is no object that has a pointer value (char*) 0 by
definition. This value is distinct from any other
This compiles for me on GCC 3.3.1 and MSVC 6.0.

The compiler is not required to catch this undefined behavior.
It's been a very long time but from what I remember, ptrdiff_t is
supposed to guarentee that it is able to hold a pointer.

Yoiu don't remember (or never understood to begin with). ptrdiff_t
is an implementation defined type. The only time subtraction is
valid is the result of subtracting two pointers into the same
array. Other uses are UNDEFINED BEHAVIOR. Read 5.7, additive
operators.

size_t is an unsigned value big enough to hold the size of any object
(that is it is the type of the return of sizeof).
On a machine with 64 bit pointers ptrdiff_t is a 64 bit integer type.

It would make very little sense to be otherwise.
It still doesn't mean anything with regard to function pointers. There have
been machines where the object pointers are one size and the instruction
pointers are larger.
 
L

llewelly

Ron Natalie said:
Because void(*)() would have to be a 64-bit type.

If code pointers are 64 bit, why wouldn't void(*)() be 64-bit?
The standard doesn't guarantee that there is any integral type that
is big enough to hold a function

pointer, but says that if there is one, you can convert back and forth to it
without information loss.

Agreed, but 5.2.10/6 guarantees that reinterpret_cast<> can be used to
covert amoungst pointer to function types without loss, without
the implementation dependency of using an integral type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,690
Members
48,796
Latest member
Greg L.

Latest Threads

Top