我有一个使用C ++ Builder 10.1 Berlin的跨平台C ++应用程序构建,并且在理解对象的生命周期处理方面存在问题,在这种情况下,字符串是在类外声明的。 我创建了一个新的表单应用程序并添加了一些代码。 cpp文件如下所示:
#include
#pragma hdrstop
#include "FmrMain.h"
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
const String Hello = "Hello";
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ShowMessage(Hello);
}
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
ShowMessage(Hello);
}
我用CLANG增强的C ++ 11编译器bcc32c编译它,运行应用程序并再次关闭表单。当调用TForm1 :: FormDestroy时,Hello已经被破坏了。当我使用经典编译器bcc32编译win32的代码时,字符串在FormDestroy之后被销毁。
有人可以解释一下或提供一些有关我必须寻找的主题的信息吗?为什么基于CLANG的编译器在这里表现不同?
修改
当我使用自定义类而不是字符串时,它更容易调试。
class Foo {
public:
Foo(){};
~Foo(){}
};
Foo A;
//--------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
}
创造和破坏就像这样。我添加了调用堆栈。
bcc32c(CLANG C ++ 11编译器)
创建Foo
:004052C0 Foo(this =:00400000)
:00405070 __cxx_global_var_init3()
:004052A3 _GLOBAL__I_a()
:00405ab7; 〜富
:321fa2b7; C:\ Program Files(x86)\ Embarcadero \ Studio \ 18.0 \ bin \ CC32C240MT.DLL
:321fa6ff CC32C240MT .__ wstartup + 0xbb
创建Form1
:004052EC TForm1(此=:00402422,__ vector_flag =' \ 0')
:0085c139 fmx240。@Fmx @ Forms @ TApplication @ CreateForm $ qqrxp17System @ TMetaClasspv + 0x5d
:0085c349 fmx240。@Fmx @ Forms @ TApplication @ RealCreateForms $ qqrv + 0x81
摧毁Foo
:004052D0~Foo(this =:0040B7DC)
:0040509E __dtor_A()
:321f6246 CC32C240MT .___ call_atexit_procs + 0x52
:321f671c CC32C240MT .___退出+ 0x20
销毁Form1
:00405868~TForm1(this =:5016E698)
bcc32(经典borland编译器)
创建Foo
:00404950 Foo :: Foo(this =:00409B74)
:004048A0 STCON0 ()
:00405727; IRoot
:322190f1; C:\ Program Files(x86)\ Embarcadero \ Studio \ 18.0 \ bin \ CC32240MT.DLL> :322193b5 CC32240MT .__ wstartup + 0xa5
创建Form1
:00404994 TForm1 :: TForm1(此=:02F2AE20,所有者=:02F39620)
:0095c139 fmx240。@Fmx @ Forms @ TApplication @ CreateForm $ qqrxp17System @ TMetaClasspv + 0x5d
:0095c349 fmx240。@Fmx @ Forms @ TApplication @ RealCreateForms $ qqrv + 0x81
销毁Form1
:00404ABC TForm1 :: ~TForm1(this =:02F2AE20)
摧毁Foo
:00404978 Foo ::〜Foo(this =:00409B74)
:0040493F STDES0 ()
:0040573f; IRoot>
:3221910f; C:\ Program Files(x86)\ Embarcadero \ Studio \ 18.0 \ bin \ CC32240MT.DLL
:3221915b; C:\ Program Files(x86)\ Embarcadero \ Studio \ 18.0 \ bin \ CC32240MT.DLL> :3221944a; C:\ Program Files(x86)\ Embarcadero \ Studio \ 18.0 \ bin \ CC32240MT.DLL
答案 0 :(得分:3)
自动创建的TForm
对象归全局TApplication
对象所有。在应用程序的main()
/ wmain()
/ WinMain()
入口点函数退出后,该对象被销毁(从而销毁其拥有的表单)。在应用程序清理期间销毁Globals。
在任一编译器中,全局String
的生命周期保证不会超过全局TApplication
对象的生命周期。您基于不同单位的全局变量的清理顺序依赖于未定义的行为。更糟糕的是,您依赖于不同框架的清理顺序!您的String
位于您自己的C ++代码中,但TApplication
对象位于基于Delphi的RTL库中。
如果String
需要在使用它的TForm
的生命周期内保持活跃状态,则应将其声明为该类的static
成员:
FmrMain.h:
//---------------------------------------------------------------------------
#ifndef FmrMainH
#define FmrMainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
static const String Hello;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
FmrMain.cpp:
//---------------------------------------------------------------------------
#include <fmx.h>
#pragma hdrstop
#include "FmrMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
const String TForm1::Hello = "Hello";
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ShowMessage(Hello);
}
void __fastcall TForm1::~TForm1()
{
ShowMessage(Hello);
}
//---------------------------------------------------------------------------
或者,使用wchar_t*
代替String
,然后您就不会遇到任何清理问题:
//---------------------------------------------------------------------------
#include <fmx.h>
#pragma hdrstop
#include "FmrMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
static const wchar_t* Hello = L"Hello";
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ShowMessage(Hello);
}
void __fastcall TForm1::~TForm1()
{
ShowMessage(Hello);
}
//---------------------------------------------------------------------------