By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,939 Members | 1,541 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,939 IT Pros & Developers. It's quick & easy.

Microsoft runtime error R6025 Pure Virtual Function Call: a technicalreport

P: n/a
This is a technical C++ post regarding the
Microsoft runtime error R6025 Pure Virtual Function Call
that sometime occurs in programs compiled with
Microsoft Visual C++ 6.0.

Please consider the following simple illegal C++ program:

class Listener {
public:
virtual void onEvent(int n) = 0;
};
class A : public Listener {
public:
Listener * listener;
int val;
explicit A(int n) {listener = this; val = n;}
virtual ~A() {}
virtual void run() {listener->onEvent(val);}
};
int main() {
A(42).run();
return 0;
}

This program is illegal because in the main() function
there is a call to A constructor but A cannot be constructed
because it does not declare the onEvent function.

When you try to compile it using g++
you correctly obtaing the following error:
virtual.cpp: In function `int main ()':
virtual.cpp:14: cannot allocate an object of type `A'
virtual.cpp:14: since the following virtual functions are abstract:
virtual.cpp:3: void Listener::onEvent (int)

But, surprise!, when you try to compile it using
the Microsoft C++ 6.0 compiler you have no error.
Only when you execute it you will obtain the infamous
Microsoft runtime error R6025 Pure Virtual Function Call.

If your application sometime suffers of R6025 error
there are two manners to discover the problem:
<1> Try to compile the program using an
alternative correct c++ compiler (like g++),
-or-
<2> Make a code inspection on the program
and try to figure out all code containg the pattern:
className(someParam).methodInvocation(otherParam)
and substitute it with:
className xxx(someParam);
xxx.methodInvocation(otherParam)

If you try <2> on the previous simple illegal C++ program
you will obtain a main() like this:
int main() {
A xxx(42);
xxx.run();
return 0;
}
and now, when you compile it with using the Microsoft C++ compiler
you will correctly obtain the error:
error C2259: 'A' : cannot instantiate abstract class ...

Short Story
===========

IMHO a C++ program error is masked by a bug
of the Microsoft C++ 6.0 compiler.
Accurate code inspection -or- using an alternative
correct C++ compiler (like g++)
may help in finding the error.

- Dario

Jul 19 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a

"Dario" <da***@despammed.com> wrote in message news:bk**********@grillo.cs.interbusiness.it...

I don't know why you feel comp.lang.c++ cares about Microsnot compiler bugs.
This program is illegal because in the main() function
there is a call to A constructor but A cannot be constructed
because it does not declare the onEvent function.


Absolutely incorect. You can not call constructors. What you have
is an attempt to create a temporary object initialzed with 42. But you
are right in that A is still abstract and the program is ill-formed when it tries
to create an A object.
Jul 19 '05 #2

P: n/a
On Thu, 18 Sep 2003 09:32:04 -0400, "Ron Natalie" <ro*@sensor.com> wrote:

"Dario" <da***@despammed.com> wrote in message news:bk**********@grillo.cs.interbusiness.it...

I don't know why you feel comp.lang.c++ cares about Microsnot compiler bugs.


"Microsoft", not a deragatory variant.

Many here care because they're in the position of using actual compilers
to produce actual code.

The more you know about compiler errors like that, the easier it is to
conclude whether some error is a language violation or a compiler error
(in the old days that was obvious, 'cause a compiler was almost never
wrong, but with modern C++ it's another story).
This program is illegal because in the main() function
there is a call to A constructor but A cannot be constructed
because it does not declare the onEvent function.


Absolutely incorect. You can not call constructors.


There's enough people on this group discussing basic _terminology_ if not
old-timers too. But for the record:

a constructor can be called.

C++ merely couples that with object allocation, as does all other languages
I know (since that's the point of a constructor), so:

a constructor for type T cannot be called on an existing type T object ...

.... by using conventional syntax, and it cannot be so called at all in a well-
defined way (using placement new that way is, I think, undefined behavior,
unless the existing object is destroyed first via explicit call of destructor).

Jul 19 '05 #3

P: n/a
Comments below.

"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
On Thu, 18 Sep 2003 09:32:04 -0400, "Ron Natalie" <ro*@sensor.com> wrote:

"Dario" <da***@despammed.com> wrote in message news:bk**********@grillo.cs.interbusiness.it...

I don't know why you feel comp.lang.c++ cares about Microsnot compiler
bugs.
"Microsoft", not a deragatory variant.

Many here care because they're in the position of using actual compilers
to produce actual code.

The more you know about compiler errors like that, the easier it is to
conclude whether some error is a language violation or a compiler error
(in the old days that was obvious, 'cause a compiler was almost never
wrong, but with modern C++ it's another story).
This program is illegal because in the main() function
there is a call to A constructor but A cannot be constructed
because it does not declare the onEvent function.
Absolutely incorect. You can not call constructors.


There's enough people on this group discussing basic _terminology_ if not
old-timers too. But for the record:

a constructor can be called.

C++ merely couples that with object allocation, as does all other

languages I know (since that's the point of a constructor), so:

a constructor for type T cannot be called on an existing type T object ....
... by using conventional syntax, and it cannot be so called at all in a well- defined way (using placement new that way is, I think, undefined behavior,
unless the existing object is destroyed first via explicit call of destructor).


The example at the bottom allocates enough memory for 10 CMyObj's. It uses
the following statements to construct and destruct the objects as needed.

m_aData[i].CBankT::CBankT();
m_aData[i].CBankT::~CBankT();
Is this a compiler loophole, or valid code?

-Kanon

// Creates a static block of memory
// that can hold several T objects.
template <class T>
class CBank_t
{
class CBankT : public T {};

CBankT * m_aData;
bool * m_aInUse;

int m_iCapacity;
int m_iSize;

public:
CBank_t(int iCapacity)
{
// allocate memory for future use
m_aData = (CBankT*)malloc(iCapacity*sizeof(CBankT));
m_aInUse = new bool[iCapacity];
memset(m_aInUse, 0, sizeof(bool)*iCapacity);

m_iSize = 0;
m_iCapacity = iCapacity;
}

T * Create()
{
int i = 0;
// Find an object not in use
while (i < m_iCapacity && m_aInUse[i])
i++;

if (i >= m_iCapacity)
return NULL;

m_aData[i].CBankT::CBankT();
m_aInUse[i] = true;
m_iSize++;

return &(m_aData[i]);
}

void Release(T * pObj)
{
int i = pObj - m_aData;

if (i < m_iCapacity)
{
m_aData[i].CBankT::~CBankT();
m_aInUse = false;
m_iSize--;
}
}

int GetSize()
{return m_iSize;}

int GetCapacity()
{return m_iCapacity;}
};

// Simple do nothing class
class CMyObj
{
int m_iX;
public:
CMyObj()
{m_iX = 0;}
~CMyObj()
{m_iX = -1;}

void SetX(int x)
{m_iX = x;}

int GetX()
{return m_iX;}

};
int main()
{
CBank_t <CMyObj> theBank(10);

CMyObj * pObj1, *pObj2;

pObj1 = theBank.Create();
pObj2 = theBank.Create();

pObj1->SetX(3);
pObj1->GetX();

pObj2->SetX(5);
pObj2->GetX();

theBank.Release(pObj1);
theBank.Release(pObj2);

return 0;
}


Jul 19 '05 #4

P: n/a
On Thu, 18 Sep 2003 13:14:54 -0500, "Kanon Wood" <Ka****@yahoo.com> wrote:
The example at the bottom allocates enough memory for 10 CMyObj's. It uses
the following statements to construct and destruct the objects as needed.

m_aData[i].CBankT::CBankT();

Is this a compiler loophole, or valid code?
That's a compiler loophole _if_ any compiler accepts it. More
specifically it's a compiler error. To construct objects in-place use
placement new (look it up).
m_aData[i].CBankT::~CBankT();
This is technically OK, I think (never used that feature, so
I'd have to check the syntax ;-) ).

That does not mean it's OK at any other level.

// Creates a static block of memory
// that can hold several T objects.
template <class T>
class CBank_t
{
class CBankT : public T {};

CBankT * m_aData;
bool * m_aInUse;

int m_iCapacity;
int m_iSize;

public:
CBank_t(int iCapacity)
{
// allocate memory for future use
m_aData = (CBankT*)malloc(iCapacity*sizeof(CBankT));

Ouch.
Hth.,

- Alf

Jul 19 '05 #5

P: n/a

"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
On Thu, 18 Sep 2003 13:14:54 -0500, "Kanon Wood" <Ka****@yahoo.com> wrote:
The example at the bottom allocates enough memory for 10 CMyObj's. It usesthe following statements to construct and destruct the objects as needed.

m_aData[i].CBankT::CBankT();

Is this a compiler loophole, or valid code?
That's a compiler loophole _if_ any compiler accepts it. More
specifically it's a compiler error. To construct objects in-place use
placement new (look it up).


VC 6.0 compiles it OK, but per your advice I replaced it with placement new.
Works fine.
m_aData[i].CBankT::~CBankT();
This is technically OK, I think (never used that feature, so
I'd have to check the syntax ;-) ).

That does not mean it's OK at any other level.


MSDN says it's OK to use with placement new.

CBank_t(int iCapacity)
{
// allocate memory for future use
m_aData = (CBankT*)malloc(iCapacity*sizeof(CBankT));

Ouch.


How would you suggest allocating this memory without constructing objects?


Hth.,

Hth?
- Alf


-Kanon
Jul 19 '05 #6

P: n/a
Alf P. Steinbach wrote:
m_aData[i].CBankT::~CBankT();

This is technically OK, I think (never used that feature, so
I'd have to check the syntax ;-) ).


I didn't look at the rest of the code very carefully, but I think
usually the syntax is

object->~Object();

(because usually you are dealing with a pointer). I can't see an obvious
problem with calling it directly on the object, but I don't know about
the explicit qualification.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #7

P: n/a
On Thu, 18 Sep 2003 14:24:56 -0500, "Kanon Wood" <Ka****@yahoo.com> wrote:
> CBank_t(int iCapacity)
> {
>// allocate memory for future use
> m_aData = (CBankT*)malloc(iCapacity*sizeof(CBankT));

Ouch.


How would you suggest allocating this memory without constructing objects?


I wouldn't... ;-)

As is so often the case in this group, the real problem is most probably
something else - when you find that you "need" something as ugly as that,
there is something very very wrong with the approach (it just makes things
infinitely worse that Bruce Eckel has such an example in his online book).

But anyway, in the hypotethical case (science fiction) where something like
that is really needed you might consider a std::vector<char> as buffer.
Btw., please don't crosspost to Microsoft newgroups, because that may drag
Microsoft-specific responses into [comp.lang.c++].

FUT: [comp.lang.c++].

Jul 19 '05 #8

P: n/a
Kanon Wood wrote:

How would you suggest allocating this memory without constructing objects?


operator new() (not the new operator) is one option.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #9

P: n/a
Dario wrote:
This is a technical C++ post regarding the
Microsoft runtime error R6025 Pure Virtual Function Call
that sometime occurs in programs compiled with
Microsoft Visual C++ 6.0.


FWIW, VC7.1 (aka VC.NET 2003) correctly identifies the error.
Jul 19 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.