Таинственное переполнение стека в конструкторе - PullRequest
5 голосов
/ 19 марта 2012

Это иерархия классов, которую использует моя программа:

enter image description here

Конструктор TForm_Upgrade_Database выглядит следующим образом:

__ fastcall TForm_Upgrade_Database :: TForm_Upgrade_Database (TComponent *Владелец, int newest_version): TForm (Владелец) {}

После попытки создания экземпляра формы

TForm_Upgrade_Database *dlg = new TForm_Upgrade_Database(this, newest_version);

моя программа выдает исключение EStackOverflow

enter image description here

Я остановил программу и снова запустил ее с точкой останова в конструкторе TForm_Upgrade_Database.После нескольких шагов callstack выглядит следующим образом:

enter image description here

Как получается, что конструктор TCustomForm продолжает пытаться вызвать конструктор своего потомка ???

Minimalконтрольный пример:

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

Ответы [ 2 ]

4 голосов
/ 21 марта 2012

TForm имеет виртуального конструктора, который принимает параметры TComponent* и int в указанном порядке.Вы переопределяете этот конструктор.Вызывая конструктор базового класса, который принимает только параметр TComponent*, вы фактически создаете рекурсивный цикл, когда эти конструкторы вызывают друг друга внутренне.

Решение - это то, что сказал искатель правды.Вам нужно изменить параметры вашего производного конструктора, чтобы вы больше не переопределяли конструктор базового класса TComponent*/int.Достаточно изменить порядок параметров, или вы можете изменить int на другой тип данных.

1 голос
/ 20 марта 2012

Я думаю, что это связано с некоторыми нестандартными решениями в библиотеке Delphi.Библиотеки VCL написаны и скомпилированы в Delphi Pascal.Сотрудничество с C ++ осуществляется через интерфейсные файлы (с расширением * .hpp).Скомпилированный двоичный код, вероятно, ищет параметры конструктора при неправильных смещениях памяти.Так что это, вероятно, проблема соглашения о вызовах.

Мне удалось создать экземпляр формул при изменении параметров в конструкторе, чтобы новый параметр был первым.

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);
...