This is class hierarchy that my program uses:
The constructor of TForm_Upgrade_Database is looking like following:
__fastcall TForm_Upgrade_Database::TForm_Upgrade_Database(TComponent* Owner, int newest_version) : TForm(Owner) { }
After trying to create instance of formular
TForm_Upgrade_Database *dlg = new TForm_Upgrade_Database(this, newest_version);
my program throws EStackOverflow exception
I stopped program and ran it again with breakpoint in TForm_Upgrade_Database constructor. After few steps callstack looks like this:
How is it that TCustomForm constructor keeps trying to call constructor of its descendant???
Minimal test case:
so_project.cpp:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "f_form.h"
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
TForm_Upgrade_Database *form = new TForm_Upgrade_Database(NULL, 10);
delete form;
form = NULL;
return 0;
}
//---------------------------------------------------------------------------
f_form.cpp:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "f_form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm_Upgrade_Database *Form1;
//---------------------------------------------------------------------------
__fastcall TForm_Upgrade_Database::TForm_Upgrade_Database(TComponent* Owner, int x)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
f_form.h:
//---------------------------------------------------------------------------
#ifndef f_formH
#define f_formH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm_Upgrade_Database : public TForm
{
__published: // IDE-managed Components
private: // User declarations
public: // User declarations
__fastcall TForm_Upgrade_Database(TComponent* Owner, int x);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm_Upgrade_Database *Form1;
//---------------------------------------------------------------------------
#endif
TForm
has a virtual construtor that takes TComponent*
and int
parameters, in that order. You are overriding that constructor. By calling the base-class constructor that only takes a TComponent*
parameter, you are in fact creating a recursive loop when those constructors call each other internally.
The solution is what truthseeker said. You have to change the parameters of your derived constructor so you are not overriding the base class TComponent*/int
constructor anymore. Changing the order of the parameters is enough, or you can change the int
to a different data type.
I think this has to do with some non-standard solutions in delphi library. VCL libraries are written and compiled in Delphi Pascal. Cooperation with C++ is made through interface files (with extension *.hpp). Compiled binary code is probably searching for constructor parameters on incorrect memory offsets. So this is probably a problem of calling convention.
I succeeded creating instance of formular when changing parameters in constructor so that the new parameter is first.
f_form.h:
__fastcall TForm_Upgrade_Database(int x, TComponent* Owner);
f_form.cpp:
__fastcall TForm_Upgrade_Database::TForm_Upgrade_Database(int x, TComponent* Owner)
: TForm(Owner)
{
}
so_project.cpp:
TForm_Upgrade_Database *form = new TForm_Upgrade_Database(10, NULL);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With