Delphi移动平台上生存期自管理一些问题的避免

今天和Delphi高手刘麻子讨论了一下移动平台上生存期自管理容易导致的一些问题.有几点体会

在移动平台上Delphi的对象是生存期自管理的,这和早期版本和现有的PC版本有很大不同.
大部分时间我们原来的代码不会有问题.我们原来的手动释放代码在移动平台也不会有问题,因为TObject.Free方法在移动平台上就是个摆设.

procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;

真正调用到对象的Destroy的只有编译器自动产生的代码.
一般有两种情况.
1. :=也就是赋值,会调用旧的变量内容的__ObjRelease减少引用计数,会调用新变量内容的__ObjAddRef增加引用计数.
2.当变量销毁时,如局部变量离开函数恢复栈的时候,如成员变量在对象的销毁时候.会调用变量内容的__ObjRelease减少引用计数.
当引用计数减到0的时候会调用到Destroy或FreeInstance真正的释放对象.

另外还有一个特殊的Attribute名字叫WeakAttribute.如果变量被[weak]修饰,那么编译器在处理这个变量的时候不会调用该变量内容的__ObjAddRef和__ObjRelease.

一切看起来都挺顺利的.但是我们的旧代码移植到移动平台上还是会有对象在我们不希望它释放的时候被释放了,导致地址出错等莫名其妙的问题.
为什么呢,因为Delphi是一种支持指针的语言.但是指针和靠引用计数生存期自管理简直是水火不相容.

比如我们把对象赋值给指针保管,然后旧的对象变量销毁的时候对象有可能就被释放.我们再用指针操作该对象的时候地址已经是无效的了.
比如我们使用Classes单元的TList而不是泛型的TList<T>来保管对象,这种代码在旧的Delphi代码中非常常见.
Classes单元中的TList是个指针的容器,就非常容易导致上面说的问题.

怎么办呢?

有一个无赖的办法.
对象在赋值给指针之前手动调用一下__ObjAddRef方法,给他的引用计数加一.这样编译器产生的生存期自管理代码就永远不会把该对象的引用计数减到零来释放了.
然后在指针变量销毁前,或者赋值别的内容前手工调用一下__ObjRelease.

比如给上面说的TList增加对象前,为防止对象被释放要调用一下对象的__ObjAddRef,响应的,在恰当的时候要调用一下__ObjRelease.

本来以为这个方法有点无赖了,发现易博龙本身RTL中也是这样的做的.嘿嘿.

class function TEncoding.GetANSI: TEncoding;
var
  LEncoding: TEncoding;
begin
  if FANSIEncoding = nil then
  begin
    LEncoding := TMBCSEncoding.Create(GetACP, 0, 0);
    if AtomicCmpExchange(Pointer(FANSIEncoding), Pointer(LEncoding), nil) <> nil then
      LEncoding.Free;
{$IFDEF AUTOREFCOUNT}
    FANSIEncoding.__ObjAddRef; //<------瞧,易博龙和我们一样"无赖"
{$ENDIF AUTOREFCOUNT}
  end;
  Result := FANSIEncoding;
end;

class destructor TEncoding.Destroy;
begin
  FreeEncodings;  //销毁代码
end;

class procedure TEncoding.FreeEncodings;
begin
  FreeAndNil(FANSIEncoding);
  FreeAndNil(FASCIIEncoding);
  FreeAndNil(FUTF7Encoding);
  FreeAndNil(FUTF8Encoding);
  FreeAndNil(FUnicodeEncoding);
  FreeAndNil(FBigEndianUnicodeEncoding);
end;

procedure FreeAndNil(var Obj);
{$IF not Defined(AUTOREFCOUNT)}
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;
{$ELSE}
begin
  TObject(Obj) := nil; //这个等价于TObject(Obj).__ObjRelease; Obj:=nil;
end;
{$ENDIF}

最后说一句,手动调用__ObjAddRef/__ObjRelease是没办法的时候做的.说句祝福:希望大家在移植旧代码到移动平台的时候都不要遇到对象生存期自管理和旧代码的兼容问题,不要被迫使用这个办法.

此条目发表在Delphi, 未分类分类目录。将固定链接加入收藏夹。

Delphi移动平台上生存期自管理一些问题的避免》有197条回应

  1. 杨权琳说:

    现在还没有开始搞移动的开发
    不过这个事情,跟直接用interface的方式一样了..
    不过自+1先,确实是比较无赖的方式。

    好多年没见过A3了,我现在也在上海

  2. 匿名说:

    看这趋势应该快把 ObjectiveC 的 ARC (Auto reference couting) 搬过来啦, 只是搬的还不完整,未来加入”所有权修饰符”,比如 __weak , __strong, __autoreleasing 。 这样就可以完全依赖编译器来管理引用计数了,然后就要考虑以前的类库怎么兼容的问题了。

  3. 匿名说:

    非常不喜欢这个特性. EMB 就非要这样不可吗?

    导致大量的老代码都变得不可靠, 全部抄出来, 重新测试和修改.
    这个可不是一般的工作量.

  4. billwillman说:

    其实我还是觉得,应该把
    TList变为TList,手动加引用计数是可以的,但感觉不规范而已。呵呵

  5. Pingback引用通告: 43ytr.icu/j/GPoAr

  6. Pingback引用通告: Èãðà ïðåñòîëîâ 8 ñåçîí Ëîñòôèëüì

  7. Pingback引用通告: Èãðà ïðåñòîëîâ 8 ñåçîí

  8. Pingback引用通告: glyxar.ru

  9. Pingback引用通告: abisko.ru

  10. Pingback引用通告: 2021

  11. Pingback引用通告: ðîêåòìåí

  12. Pingback引用通告: wwin-tv.com

  13. Pingback引用通告: Video

  14. Pingback引用通告: Watch

  15. Pingback引用通告: watch online

  16. Pingback引用通告: 00-tv.com

  17. Pingback引用通告: 4serial.com

  18. Pingback引用通告: tureckie_serialy_na_russkom_jazyke

  19. Pingback引用通告: tureckie_serialy

  20. Pingback引用通告: serialy

  21. Pingback引用通告: +1+

  22. Pingback引用通告: æóêè+2+ñåðèÿ

  23. Pingback引用通告: Ñìîòðåòü ñåðèàëû îíëàéí âñå ñåðèè ïîäðÿä

  24. Pingback引用通告: Ñìîòðåòü âñå ñåðèè ïîäðÿä

  25. Pingback引用通告: âûòîïêà âîñêà

  26. Pingback引用通告: ++++++

  27. Pingback引用通告: HD-720

  28. Pingback引用通告: guardians+of+the+galaxy+2

  29. Pingback引用通告: strong woman do bong soon

  30. Pingback引用通告: my id is gangnam beauty

  31. Pingback引用通告: guardians of the galaxy vol 2

  32. Pingback引用通告: 2020

  33. Pingback引用通告: kpop+star+season+6+ep+9

  34. Pingback引用通告: 1 2 3 4 5 6 7 8 9 10

  35. Pingback引用通告: Kinokrad 2019 Kinokrad Hd

  36. Pingback引用通告: Kinokrad

  37. Pingback引用通告: filmy-kinokrad

  38. Pingback引用通告: kinokrad-2019

  39. Pingback引用通告: filmy-2019-kinokrad

  40. Pingback引用通告: serial

  41. Pingback引用通告: cerialest.ru

  42. Pingback引用通告: youtube2019.ru

  43. Pingback引用通告: dorama hdrezka

  44. Pingback引用通告: movies hdrezka

  45. Pingback引用通告: HDrezka

  46. Pingback引用通告: kinosmotretonline

  47. Pingback引用通告: LostFilm HD 720

  48. Pingback引用通告: trustedmdstorefy.com

  49. Pingback引用通告: bofilm ñåðèàë

  50. Pingback引用通告: bofilm

  51. Pingback引用通告: 1 seriya

  52. Pingback引用通告: Êîíñóëüòàöèÿ ïñèõîëîãà

  53. Pingback引用通告: topedstoreusa.com

  54. Pingback引用通告: hqcialismht.com

  55. Pingback引用通告: viagramdtrustser.com

  56. Pingback引用通告: rick and morty season 3

  57. Pingback引用通告: See-Season-1

  58. Pingback引用通告: Evil-Season-1

  59. Pingback引用通告: Evil-Season-2

  60. Pingback引用通告: Evil-Season-3

  61. Pingback引用通告: Evil-Season-4

  62. Pingback引用通告: Dollface-Season-1

  63. Pingback引用通告: Queer-Eye-We-re-in-Japan-Season-1

  64. Pingback引用通告: serial 2020

  65. Pingback引用通告: Dailymotion

  66. Pingback引用通告: Watch+movies+2020

  67. Pingback引用通告: Netflix Original Movies

  68. Pingback引用通告: serial-video-film-online

  69. Pingback引用通告: tvrv.ru

  70. Pingback引用通告: 1plus1serial.site

  71. Pingback引用通告: #1plus1

  72. Pingback引用通告: 1plus1

  73. Pingback引用通告: Watch Movies Online

  74. Pingback引用通告: Film

  75. Pingback引用通告: Film 2020

  76. Pingback引用通告: Film 2021

  77. Pingback引用通告: watch online TV LIVE 2020

  78. Pingback引用通告: parazity-oskar-2020

  79. Pingback引用通告: human design

  80. Pingback引用通告: DSmlka

  81. Pingback引用通告: viagra

  82. Pingback引用通告: viagra online

  83. Pingback引用通告: +

  84. Pingback引用通告: ¯jak Son³k

  85. Pingback引用通告: astrolog

  86. Pingback引用通告: film-kalashnikov-watch

  87. Pingback引用通告: generic cialis

  88. Pingback引用通告: cialis online

  89. Pingback引用通告: pobachennya u vegas

  90. Pingback引用通告: Proshanie so Stalinym

  91. Pingback引用通告: strelcov 2020

  92. Pingback引用通告: t-34

  93. Pingback引用通告: online pharmacy

  94. Pingback引用通告: canadian pharmacy

  95. Pingback引用通告: Beograd film 2020

  96. Pingback引用通告: psiholog

  97. Pingback引用通告: psixolog

  98. Pingback引用通告: psyhelp_on_line

  99. Pingback引用通告: coronavirus

  100. Pingback引用通告: PSYCHOSOCIAL

  101. Pingback引用通告: rasstanovka hellinger

  102. Pingback引用通告: Cherekasi film 2020

  103. Pingback引用通告: film doktor_liza

  104. Pingback引用通告: djoker film

  105. Pingback引用通告: t.me/psyhell

  106. Pingback引用通告: Ïñèõîëîã îíëàéí

  107. Pingback引用通告: bitly.com

  108. Pingback引用通告: viagra 100mg

  109. Pingback引用通告: viagra price

  110. Pingback引用通告: viagra generic

  111. Pingback引用通告: viagra coupon

  112. Pingback引用通告: cheap viagra

  113. Pingback引用通告: cialis

  114. Pingback引用通告: cialis coupon

  115. Pingback引用通告: canadian pharmacy cialis

  116. Pingback引用通告: cialis 5mg

  117. Pingback引用通告: rlowcostmd.com

  118. Pingback引用通告: bitly

  119. Pingback引用通告: movies-tekstmovies-tekst

  120. Pingback引用通告: Zemlyane 2005 smotret onlajn

  121. Pingback引用通告: smotret onlajn besplatno v kachestve hd 1080

  122. Pingback引用通告: gusmeasu.com

  123. Pingback引用通告: movies-unhinged-film

  124. Pingback引用通告: malenkie-zhenshhiny-2020

  125. Pingback引用通告: dom 2

  126. Pingback引用通告: zoom-psykholog

  127. Pingback引用通告: zoom-viber-skype

  128. Pingback引用通告: Vratar Galaktiki Film, 2020

  129. Pingback引用通告: Vratar

  130. Pingback引用通告: Cherkassy 2020

  131. Pingback引用通告: chernobyl-hbo-2019-1-sezon

  132. Pingback引用通告: moskva-psiholog

  133. Pingback引用通告: batmanapollo.ru

  134. Pingback引用通告: 323

  135. Pingback引用通告: 525

  136. Pingback引用通告: dom2-ru

  137. Pingback引用通告: Tenet Online

  138. Pingback引用通告: psy psy psy psy

  139. Pingback引用通告: krsmi.ru

  140. Pingback引用通告: like-v.ru

  141. Pingback引用通告: CFOSPUK

  142. Pingback引用通告: MAMprEj

  143. Pingback引用通告: fgu0ygW

  144. Pingback引用通告: batmanapollo

  145. Pingback引用通告: tsoy

  146. Pingback引用通告: 44548

  147. Pingback引用通告: 44549

  148. Pingback引用通告: hod-korolevy-2020

  149. Pingback引用通告: HD

  150. Pingback引用通告: 158444

  151. Pingback引用通告: groznyy-serial-2020

  152. Pingback引用通告: 38QvPmk

  153. Pingback引用通告: bitly.com/doctor-strange-hd

  154. Pingback引用通告: bitly.com/eternals-online

  155. Pingback引用通告: bitly.com/maior-grom

  156. Pingback引用通告: matrica-film

  157. Pingback引用通告: dzhonuikfilm4

  158. Pingback引用通告: bitly.com/batman20212022

  159. Pingback引用通告: bitly.com/venom-2-smotret-onlajn

  160. Pingback引用通告: bitly.com/nevremyaumirat

  161. Pingback引用通告: bitly.com/kingsmankingsman

  162. Pingback引用通告: bitly.com/3zaklyatie3

  163. Pingback引用通告: bitly.com/1dreykfilm

  164. Pingback引用通告: bitly.com/topgunmavericktopgun

  165. Pingback引用通告: bitly.com/flash2022

  166. Pingback引用通告: bitly.com/fantasticheskietvari3

  167. Pingback引用通告: bitly.com/wonderwoman1984hd

  168. Pingback引用通告: 1444

  169. Pingback引用通告: cleantalkorg2.ru

  170. Pingback引用通告: 232dfsad

  171. Pingback引用通告: cleantalkorg2.ru/sitemap.xml

  172. Pingback引用通告: join vk

  173. Pingback引用通告: vk login

  174. Pingback引用通告: svaty—7—sezon

  175. Pingback引用通告: svaty 7 sezon

  176. Pingback引用通告: svaty 7

  177. Pingback引用通告: tik tok

  178. Pingback引用通告: 666

  179. Pingback引用通告: The Revenant

  180. Pingback引用通告: 2021

  181. Pingback引用通告: D4

  182. Pingback引用通告: 777

  183. Pingback引用通告: link

  184. Pingback引用通告: 4569987

  185. Pingback引用通告: news news news

  186. Pingback引用通告: psy

  187. Pingback引用通告: psy2022

  188. Pingback引用通告: projectio-freid

  189. Pingback引用通告: kinoteatrzarya.ru

  190. Pingback引用通告: topvideos

  191. Pingback引用通告: afisha-kinoteatrov.ru

  192. Pingback引用通告: Ukrainskie-serialy

  193. Pingback引用通告: site

  194. Pingback引用通告: top

  195. Pingback引用通告: soderzhanki-3-sezon-2021.online

评论已关闭。