我有一个疑难问题解决不了。
需要懂得argument passing stack frame才能解决的问题,下面是例子:用GNU compiler,一切都很好,但用VC++,就crash了。
如果你能帮我提示,将不胜感激。请email: *****ss1966@yahoo.com
PS.: 有人告诉我只能用Assembly写,但我一点都不懂Assembly。我看了一个解释,什么也看不明白。。。http://www.codeguru.com/Cpp/misc/misc/stack/article.php/c3875
-----------------header file classdef.hpp-------------
#include “iostream"
#include ”stdarg.h"
/*
**
** CBase
** ^ ^
** / \
** / \
** / \
** / \
** CWrapper -----> CDerive
**
**
** CWrapper class knows everything about CBase. Its purpose is
** for message passing to the real object (_base)
**
*/
#define PASTE(x, y) x ## y
#define VFN_DECL(n) \
virtual void *PASTE(VFn,n)(...)
class CBase
{
public:
virtual void foo0() {}
CBase();
virtual ~CBase();
virtual void foo1();
virtual void foo2();
virtual int foo3(int, double);
virtual void foo4(const char *, double);
private:
// to be used specifically by CWrapper
friend class CWrapper;
void* callVirt(int n, va_list ap);
};
class CWrapper : public CBase
{
public:
virtual void foo0() {} // vf 1
CWrapper(CBase *base) :
_base(base) {
}
virtual ~CWrapper(); // vf 2
virtual void foo1(); // vf 3
virtual void foo2(); // vf 3
virtual int foo3(int, double); // vf 3
virtual void foo4(const char *, double); // vf 3
// define a big virtual table
VFN_DECL(7);
VFN_DECL(8);
VFN_DECL(9);
VFN_DECL(10);
VFN_DECL(11);
VFN_DECL(12);
VFN_DECL(13);
VFN_DECL(14);
VFN_DECL(15);
private:
// the real object
CBase *_base;
};
class CDerive : public CBase
{
public:
virtual void foo0() {}
CDerive() {}
virtual ~CDerive();
virtual void foo2();
virtual void foo4(const char *, double);
// additional virtual functions
virtual void foo5();
virtual int foo6(const char *, double);
virtual void foo7();
virtual char * foo8(double, int, float, char, char *, double);
virtual void foo9();
};
-------------------source file classdef.cpp---------------------
#include "classdef.hpp"
typedef void* (*vfunc)(CBase*, ...);
// call nth virtual function
void* CBase::callVirt(int n, va_list ap)
{
vfunc **vf = (vfunc**)this;
int pos=n;
/*
** Note: GNU's destructor occupy 2 entries
*/
#ifdef WNT
pos--;
#endif
// assuming max args are 9!
const int MAX_ARGS = 9;
unsigned long arg[MAX_ARGS];
for (int i=0; i < MAX_ARGS; i++) arg[i] = va_arg(ap, unsigned long);
void* result = (*vf)[pos](this,
arg[0], arg[1], arg[2],
arg[3], arg[4], arg[5],
arg[6], arg[7], arg[8]);
return result;
}
CBase::CBase()
{
std::cout << "CBase::CBase called\n";
}
CBase::~CBase()
{
std::cout << "\nCBase::~CBase called\n";
}
void CBase::foo1()
{
std::cout << "CBase::foo1 called\n";
}
void CBase::foo2()
{
std::cout << "CBase::foo2 called\n";
}
int CBase::foo3(int i, double d)
{
std::cout << "CBase::foo3 called"
<< ", i = " << i
<< ", d = " << d
<< std::endl;
return int(i+d);
}
void CBase::foo4(const char *s, double d)
{
std::cout << "CBase::foo4 called"
<< ", s = " << s
<< ", d = " << d
<< std::endl;
}
/////////////////////////////////////////////////
CWrapper::~CWrapper()
{
std::cout << "\nCWrapper::~CWrapper called\n";
}
void CWrapper::foo1()
{
_base->foo1();
}
void CWrapper::foo2()
{
_base->foo2();
}
int CWrapper::foo3(int i, double d)
{
return _base->foo3(i, d);
}
void CWrapper::foo4(const char *s, double d)
{
_base->foo4(s, d);
}
#ifdef WNT
#define VFN_IMPL(n) \
void *CWrapper::PASTE(VFn,n)(...) \
{ \
va_list ap; \
va_start(ap, *this); \
void *r = _base->callVirt(n, ap); \
va_end(ap); \
return r; \
}
#else
#define VFN_IMPL(n) \
void *CWrapper::PASTE(VFn,n)(...) \
{ \
va_list ap; \
va_start(ap, this); \
void *r = _base->callVirt(n, ap); \
va_end(ap); \
return r; \
}
#endif
VFN_IMPL(7)
VFN_IMPL(8)
VFN_IMPL(9)
VFN_IMPL(10)
VFN_IMPL(11)
VFN_IMPL(12)
VFN_IMPL(13)
VFN_IMPL(14)
VFN_IMPL(15)
//////////////////////////////////
CDerive::~CDerive()
{
std::cout << "CDerive::~CDerive called\n";
}
void CDerive::foo2()
{
std::cout << "CDerive::foo2 called\n";
}
void CDerive::foo4(const char *s, double d)
{
std::cout << "CDerive::foo4 called"
<< ", s = " << s
<< ", d = " << d
<< std::endl;
}
void CDerive::foo5()
{
std::cout << "CDerive::foo5 called\n";
}
int CDerive::foo6(const char *s, double d)
{
std::cout << "CDerive::foo6 called"
<< ", s = " << s
<< ", d = " << d
<< std::endl;
return 99;
}
void CDerive::foo7()
{
std::cout << "CDerive::foo7 called\n";
}
char * CDerive::foo8(double a, int b, float c, char d, char *e, double f)
{
std::cout << "CDerive::foo8 called: "
<< "a = " << a
<< ", b = " << b
<< ", c = " << c
<< ", d = " << d
<< ", e = " << e
<< ", f = " << f
<< std::endl;
return e;
}
void CDerive::foo9()
{
std::cout << "CDerive::foo9 called\n";
}
----------main.cpp------------
#include "classdef.hpp"
int main()
{
CDerive *obj = (CDerive*) new CWrapper(new CDerive());
printf("-------------------------------\n");
obj->foo1();
obj->foo2();
obj->foo3(3, 4.43);
obj->foo4("aaa", 3.4);
obj->foo5();
obj->foo6("ccc", 3.2);
printf("foo6 = %d\n", obj->foo6("This is a test", 5.2321));
obj->foo7();
printf("foo8 = %s\n", obj->foo8(2.345, 5, 3.21f, 'c', "String Array", 63.455));
obj->foo9();
printf("-------------------------------\n");
return 0;
}