Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Application Programming › __purecall - What is this and why does my program crash with error "pure virtual function call"?
New Posts  All Forums:Forum Nav:

__purecall - What is this and why does my program crash with error "pure virtual function call"?

post #1 of 3
Thread Starter 
We have all seen it at least once in our time of using computers - as a programmer or as a user, and it looks a little bit like this:



R6025 - pure virtual function call: What is this and why is my program crashing with this error?

To find out what is going here we first need to dive into an object oriented programming concept called virtual functions. Both C++ and C# implement this concept. A virtual function is simply a function that always calls the most derived implementation - and even if the call was from the base/root class. It is important to note, however that C++ objects change their type during construction, whereas C# objects exist as their final (i.e. derived) type before construction.

Let's take a C++ code example to illustrate this semantic:
Code:
// I like comments.
class Vehicle
{
public:
    Vehicle()
    {
        Start(); 
    }

    virtual void Start()
    {
        cout << "I am a vehicle.\r\n";
    }
};

// I like comments.
class Car : public Vehicle
{
public:
    virtual void Start()
    {
        cout << "And now, I am a car.\r\n"; 
    }
};

When we create an object of type Car, in C++ the object type starts out as its base class, i.e. a Vehicle. During construction of a Car, the Vehicle::Vehicle() constructor is executed while the object is still a Vehicle and this means that our call to Start() actually invokes Vehicle::Start rather than Car::Start. After the Vehicle constructor completes, the object then becomes a Car and the Car::Car() constructor is executed and this time around the call to Start() goes to Car::Start.

If we put this test code in a sample program and create a new instance of type Car, the output will be the following:
Code:
I am vehicle.
And now, I am a car.

You may or may not have noticed that some programming tips do not recommend calling virtual functions from a constructor - and this is why. The call to a virtual function in a constructor is dependent on what stage of construction the object is at, and may product unexpected results.
If we modified this code to use C# instead, we will find that output will actually print "And now, I am a car." twice, because as previously mentioned a C# object exists as its final, derived type before construction.

Great, so what the hell has all of this got to do with a pure virtual function call and the crash that results from it?

In addition to virtual functions, C++ (and also C#, which calls the concept "abstract") implement pure virtual functions. A abstract or pure virtual function is a method that is declared in the base/root class, but which its implementation is provided in a child class.

Focusing on C++ now - the function that spits out this error is in the C++ runtime and is called __purecall. Let us have a look what a pure virtual function looks like in C++:
Code:
class Vehicle 
{
public:
    Vehicle()
    {
        Start();
    }

    virtual void Start() = 0;
};

// Code from above example.
class Car : public Vehicle
{
public:
    void Start()
    {
        cout << "I can only be a car!\r\n"; 
    }
};

We simply use the = 0 syntax to declare a function as abstract (pure virtual) in C++. Here is where the flames appear - if you attempt to create a new instance of Car the root class will attempt to call Vehicle::Start() in its constructor (which, remember from above, happens because the object first exists as its base type) - except this time the function doesn't really exist because it is a pure virtual function. What happens now? Yep you guessed it:



Uh, who the heck would actually do something as stupid as this from the base class' constructor, you ask?

This is just our example, of course this mistake is hardly that obvious! What I usually see is that the call to a pure virtual function is deeply nested somewhere inside the calls tack of the constructor - the debugger will help you tracking down the source of the pure virtual function call.

smile.gif

Bonus reading: I get a pure virtual function call error, but I'm not calling a virtual function from my constructor! (No, really, I'm not)

Usually the R6025 error occurs when you call a pure virtual function from a constructor - but there is another scenario where it can occur also, and this is when you may call a pure virtual function from an object that has already been destroyed (or destructed). This scenario requires some knowledge of how methods are implemented in C++ (namely, vtables) - and might be a topic I may cover in the future.

If you somehow manage to call a method on some object that you - or someone else! - has already destroyed, the behavior will of course, be undefined. When this happens during runtime, the actual method call will run with whatever garbage is in memory from where the object used to live. If you get REALLY lucky, the contents of memory in said area might look good enough that the method being executed does not even blink an eyelid. Or maybe it won't notice for a while... or (best case!), it won't even run at all!

When you receive the pure virtual function call error in this scenario, you have hit the "it won't even run at all" end of the stick. What is happening is that the object corpse still has a vtable, which is actually the vtable to the base class (so we can technically say that the object technically exists as its base type, albeit destroyed). This vtable is the one that has the __purecall pointers for all the pure virtual functions you defined in the class, so ultimately the function you called is the C++ runtime __purecall function, and as we know from above, this is the function that chucks up the error message and crashes/terminates our program.
Edited by tompsonn - 8/31/12 at 3:38am
My System
(30 items)
 
"Zeus"
(13 items)
 
 
CPUMotherboardGraphicsRAM
Intel Core i5 2500K (4.5ghz @ 1.320v) Gigabyte Z68X-UD3R-B3 MSI R7970 Lightning Corsair 16GB (4x4GB) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Crucial M4 128GB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 7 Ultimate 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2212HM Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Microsoft IntelliMouse Optical  XTRAC Ripper XXL 
AudioAudioAudioAudio
Westone W3 IEMs RE-272 IEMs Shure SE-215 IEMs Schiit Bifrost DAC 
AudioAudio
Schiit Asgard 2 amp HiVi Swan M50W 2.1 
CPUMotherboardGraphicsRAM
Intel Core i7 950 GA-X58-UD3R Radeon HD 5450  24GB Corsair @ 1333mhz 
Hard DriveOSPowerCase
4x WD Cavair Red 1TB in RAID 0 Windows Server 2008 R2 x64 Corsair HX-520 LianLi LanCool 
  hide details  
Reply
My System
(30 items)
 
"Zeus"
(13 items)
 
 
CPUMotherboardGraphicsRAM
Intel Core i5 2500K (4.5ghz @ 1.320v) Gigabyte Z68X-UD3R-B3 MSI R7970 Lightning Corsair 16GB (4x4GB) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Crucial M4 128GB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 7 Ultimate 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2212HM Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Microsoft IntelliMouse Optical  XTRAC Ripper XXL 
AudioAudioAudioAudio
Westone W3 IEMs RE-272 IEMs Shure SE-215 IEMs Schiit Bifrost DAC 
AudioAudio
Schiit Asgard 2 amp HiVi Swan M50W 2.1 
CPUMotherboardGraphicsRAM
Intel Core i7 950 GA-X58-UD3R Radeon HD 5450  24GB Corsair @ 1333mhz 
Hard DriveOSPowerCase
4x WD Cavair Red 1TB in RAID 0 Windows Server 2008 R2 x64 Corsair HX-520 LianLi LanCool 
  hide details  
Reply
post #2 of 3
What happens behind the scenes:

First the Vehicle constructor is called, and at this point the function pointers in the vtable point to msvcrt!__purecall. The pointers change to those of the next class right before its constructor is called.
Akiyama Mio
(13 items)
 
  
CPUMotherboardGraphicsRAM
E6420 @ stock, 0.98v Asus P5N-E SLI Gainward GTX 460 1GB @ 800/1600/1900 2x2GB Kingston @ 800MHz 5-5-5-15 2T 
Hard DriveOptical DriveOSMonitor
WD 250GB, 320GB SATA/3, 16MB Cache, Seagate 1TB LG GSA-H62N 18x SATA Ubuntu 9.10 x86 & Win7 x86 Asus VW222U 
KeyboardPowerCase
Logitech Classic Corsair 650HX NZXT Apollo Black 
  hide details  
Reply
Akiyama Mio
(13 items)
 
  
CPUMotherboardGraphicsRAM
E6420 @ stock, 0.98v Asus P5N-E SLI Gainward GTX 460 1GB @ 800/1600/1900 2x2GB Kingston @ 800MHz 5-5-5-15 2T 
Hard DriveOptical DriveOSMonitor
WD 250GB, 320GB SATA/3, 16MB Cache, Seagate 1TB LG GSA-H62N 18x SATA Ubuntu 9.10 x86 & Win7 x86 Asus VW222U 
KeyboardPowerCase
Logitech Classic Corsair 650HX NZXT Apollo Black 
  hide details  
Reply
post #3 of 3
Thread Starter 
Quote:
Originally Posted by Coma View Post

What happens behind the scenes:
First the Vehicle constructor is called, and at this point the function pointers in the vtable point to msvcrt!__purecall. The pointers change to those of the next class right before its constructor is called.

See "bonus reading" tongue.gif
Thanks for adding!
My System
(30 items)
 
"Zeus"
(13 items)
 
 
CPUMotherboardGraphicsRAM
Intel Core i5 2500K (4.5ghz @ 1.320v) Gigabyte Z68X-UD3R-B3 MSI R7970 Lightning Corsair 16GB (4x4GB) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Crucial M4 128GB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 7 Ultimate 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2212HM Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Microsoft IntelliMouse Optical  XTRAC Ripper XXL 
AudioAudioAudioAudio
Westone W3 IEMs RE-272 IEMs Shure SE-215 IEMs Schiit Bifrost DAC 
AudioAudio
Schiit Asgard 2 amp HiVi Swan M50W 2.1 
CPUMotherboardGraphicsRAM
Intel Core i7 950 GA-X58-UD3R Radeon HD 5450  24GB Corsair @ 1333mhz 
Hard DriveOSPowerCase
4x WD Cavair Red 1TB in RAID 0 Windows Server 2008 R2 x64 Corsair HX-520 LianLi LanCool 
  hide details  
Reply
My System
(30 items)
 
"Zeus"
(13 items)
 
 
CPUMotherboardGraphicsRAM
Intel Core i5 2500K (4.5ghz @ 1.320v) Gigabyte Z68X-UD3R-B3 MSI R7970 Lightning Corsair 16GB (4x4GB) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Crucial M4 128GB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 7 Ultimate 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2212HM Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Microsoft IntelliMouse Optical  XTRAC Ripper XXL 
AudioAudioAudioAudio
Westone W3 IEMs RE-272 IEMs Shure SE-215 IEMs Schiit Bifrost DAC 
AudioAudio
Schiit Asgard 2 amp HiVi Swan M50W 2.1 
CPUMotherboardGraphicsRAM
Intel Core i7 950 GA-X58-UD3R Radeon HD 5450  24GB Corsair @ 1333mhz 
Hard DriveOSPowerCase
4x WD Cavair Red 1TB in RAID 0 Windows Server 2008 R2 x64 Corsair HX-520 LianLi LanCool 
  hide details  
Reply
New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Application Programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Application Programming › __purecall - What is this and why does my program crash with error "pure virtual function call"?