C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

What's wrong with this segment of code?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Andy
Guest





PostPosted: Fri Apr 29, 2005 8:42 am    Post subject: What's wrong with this segment of code? Reply with quote



Hi,

Sorry for the naive question. What I did here is to check the value of
pointers to member functions, and try to call these member function via
member functio pointers.
But running with gcc, it gives out segment fault. What's wrong with my
code?

Here is the code:


#include <iostream>

using namespace std;

class A{
public:
int method1(int a, int b){ cout<<"Hello,world"; return 0; }
int method2(int a, int b) { return a + b; }
int method3(int x, int y) { return x * x;}
};


void conv_ptr(void * ptr, char* buf)
{
char * str = (char*)ptr;
int i;
for(i = 0; i < 4 ; i++)
sprintf(buf+i*2, "%.2x", str[i]);
buf[8] = 0;
}


int main()
{
A a;

int (A::*ptr) (int, int) ;
char buf[9];

ptr = &A::method1;
conv_ptr(&ptr, buf);
cout<<"ptr ="<
cout<<(a.*ptr)(5,5)<

ptr = &A::method2;
conv_ptr(&ptr, buf);
cout<<"ptr ="<
cout<<(a.*ptr)(5,5)<
ptr = &A::method3;
conv_ptr(&ptr, buf);
cout<<"ptr ="<
cout<<(a.*ptr)(5,5)< }


Thanks !

Andy


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Sat Apr 30, 2005 11:19 am    Post subject: Re: What's wrong with this segment of code? Reply with quote



Andy wrote:

Quote:
Sorry for the naive question. What I did here is to check the
value of pointers to member functions, and try to call these
member function via member functio pointers. But running with
gcc, it gives out segment fault. What's wrong with my code?

Buffer overrun. I'm tempted to say: "you asked for it, you got
it"; it's extremely difficult to write a correct program using
sprintf (and imposible to write one which is both correct and
maintainable).

Quote:
Here is the code:

#include <iostream

using namespace std;

class A{
public:
int method1(int a, int b){ cout<<"Hello,world"; return 0; }
int method2(int a, int b) { return a + b; }
int method3(int x, int y) { return x * x;}
};

void conv_ptr(void * ptr, char* buf)
{
char * str = (char*)ptr;
int i;
for(i = 0; i < 4 ; i++)
sprintf(buf+i*2, "%.2x", str[i]);

And how big is buf?

Note that on most machines, char will be signed. str[i]
converts implicitly to int when passed as a variadic arg -- if
char is signed, this will sometimes be a negative number. The
format specifier %.2x treats this (the bit pattern, not the
value -- the normal rules of conversion don't apply) as an
unsigned int, and the bit pattern of a negative int will usually
result in a pretty large unsigned number. From the values of
your magic constants, I'd guess that you're on a 32 bit machine,
which means that you'll generate 8 digits, instead of 2. If the
target buffer isn't big enough...

Quote:
buf[8] = 0;

sprintf does append a '' to the end. (Of course, in your
case, the "end" might not be where you think it is:-).)

Quote:
}

What's wrong with something like:

std::string
dump( void* value, size_t size )
{
std::ostringstream s ;
s.setf( std::ios::hex, std::ios::basefield ) ;
s.fill( '0' ) ;
unsigned char* p = static_cast< unsigned char* >( value )
;
// unsigned char, to avoid the problem
// mentionned above.

for ( size_t i = 0 ; i < size ; ++ i ) {
s << std::setw( 2 ) << (int)[[ i ] ;
// conversion to int so that the stream formats
// it as a numeric value, rather than treating
// it as a character.
}
return s.str() ;
}

This way, you're sure that there are no buffer overflow
problems.

Quote:
int main()
{
A a;

int (A::*ptr) (int, int) ;
char buf[9];

Which won't be big enough if the last byte passed is greater
than 0x7F.

Quote:
ptr = &A::method1;
conv_ptr(&ptr, buf);

You do realize that the size of a pointer to member isn't
necessarily four, even on a 32 bit machine. (The size of a
pointer to member function will typically be at least twice the
size of a normal pointer, often even more. Unless the
implemention uses trampolines, which is, I think, the case of
g++.)

Quote:
cout<<"ptr ="<

Using the above function:

std::cout << "ptr = " << dump( &ptr, sizeof( ptr ) ) << std::endl ;

Quote:
cout<<(a.*ptr)(5,5)<
ptr = &A::method2;
conv_ptr(&ptr, buf);
cout<<"ptr ="<
cout<<(a.*ptr)(5,5)<
ptr = &A::method3;
conv_ptr(&ptr, buf);
cout<<"ptr ="<
cout<<(a.*ptr)(5,5)< }

If you really want to start understanding pointers to member
functions, you'll have to dump some which contain pointers to
virtual functions. Maybe once as a int(B::*)(int,int), and once
as a int(D::*)(int,int). You might want to see what effect (if
any) multiple base classes and virtual bases have. You might
want to assign a int(B::*)(int,int) to a int(D::*)(int,int), and
dump both.

You might also want to try it with different compilers. Not all
compilers use the same implementation.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Nickolay Merkin
Guest





PostPosted: Sat Apr 30, 2005 11:29 am    Post subject: Re: What's wrong with this segment of code? Reply with quote



Nice feature...
I played with VC6, and found that

template<class T>
void conv_ptr(T* ptr, char* buf)
{
char * str = (char*)ptr;
int i;
for(i = 0; i < 4 ; i++)
sprintf(buf+i*2, "%.2x", str[i]);
buf[8] = 0;
}

prints 30124000, 60124000, ff124000

but if I turn back to

void conv_ptr(void* ptr, char* buf)

it prints
ff124000, ff124000, ff124000

Moreover, when I added fourth method, I got
ff124000, ff124000, ff124000, 00134000
in both cases.

It seems that getting address of a pointer-to-member-function variable
is undefined.
But why?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Nickolay Merkin
Guest





PostPosted: Sat Apr 30, 2005 11:34 am    Post subject: Re: What's wrong with this segment of code? Reply with quote

I posted this question on RSDN (www.rsdn.ru) and they noticed me
that
char * str = (char*)ptr;
should be replaced with
unsigned char * str = (unsigned char*)ptr;

Aha! I caught what happens.
Some of these bytes have high bit=1,
and treated as negative char values.
Passing a char to ... (in sprintf) promotes it to int,
so these bytes are treated as negative ints.
sprintf %.2x prints AT LEAST 2 hex digits,
but a negative int is a very big unsigned, so sprintf puts 8
characters.
Beginning with i=1 and more, we overrun the char buf[8] and shoot the
stack.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Martin Bonner
Guest





PostPosted: Sat Apr 30, 2005 4:13 pm    Post subject: Re: What's wrong with this segment of code? Reply with quote


k... (AT) gabi-soft (DOT) fr wrote:

Quote:
conv_ptr(&ptr, buf);

You do realize that the size of a pointer to member isn't
necessarily four, even on a 32 bit machine.

But he isn't displaying the pointer-to-member. He is displaying the
address of the object called 'ptr' (which happens to be of type pointer
to member).

This may well the OPs next problem of course. He needs to start
dumping the content of ptr rather than its address.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.