繁体   English   中英

bcc32和bcc32c对象生存期之间的区别

[英]Difference between bcc32 and bcc32c object lifetime

我有一个使用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编译器)

  1. 创建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

  2. 创建Form1

    :004052EC TForm1(this =:00402422,__ctor_flag ='\\ 0')
    :0085c139 fmx240。@ Fmx @ Forms @ TApplication @ CreateForm $ qqrxp17System @ TMetaClasspv + 0x5d
    :0085c349 fmx240。@ Fmx @ Forms @ TApplication @ RealCreateForms $ qqrv + 0x81

  3. 销毁

    :004052D0〜Foo(this =:0040B7DC)
    :0040509E __dtor_A()
    :321f6246 CC32C240MT .___ call_atexit_procs + 0x52
    :321f671c CC​​32C240MT .___退出+ 0x20

  4. 销毁Form1

    :00405868〜TForm1(this =:5016E698)

bcc32(经典borland编译器)

  1. 创建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

  2. 创建Form1

    :00404994 TForm1 :: TForm1(this =:02F2AE20,Owner =:02F39620)
    :0095c139 fmx240。@ Fmx @ Forms @ TApplication @ CreateForm $ qqrxp17System @ TMetaClasspv + 0x5d
    :0095c349 fmx240。@ Fmx @ Forms @ TApplication @ RealCreateForms $ qqrv + 0x81

  3. 销毁Form1

    :00404ABC TForm1 ::〜TForm1(this =:02F2AE20)

  4. 销毁

    :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

自动创建的TForm对象由全局TApplication对象拥有。 在应用程序的main() / wmain() / WinMain()入口点函数退出 ,该对象将被销毁(从而销毁其拥有的Forms)。 全局变量在应用程序清理期间被破坏。

在任何一个编译器中,不能保证全局String的生存期超过全局TApplication对象的生存期。 您依赖于未定义的行为 ,该行为基于不同单元之间全局变量的清除顺序。 更糟糕的是,您依赖于不同框架之间的清理顺序! 您的String在您自己的C ++代码中,但是TApplication对象在基于Delphi的RTL库中。

如果您的String需要在使用它的TForm的生命周期内保持活动状态, 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);
}
//---------------------------------------------------------------------------

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM