2009-07-16 12 views

Antwort

27

Der Quellcode von CoreFoundation ist öffentlich verfügbar. Insbesondere für Snow Leopard der Code CFRelease ist in http://www.opensource.apple.com/source/CF/CF-550/CFRuntime.c

Hier ist, was der relevante Teil wie folgt aussieht:

void CFRelease(CFTypeRef cf) { 
    if (NULL == cf) HALT; 
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED 
    if (CF_IS_COLLECTABLE(cf)) { 
     if (CFTYPE_IS_OBJC(cf)) { 
      // release the GC-visible reference. 
      auto_zone_release(auto_zone(), (void*)cf); 
     } else { 
      // special-case CF objects for better performance. 
      _CFRelease(cf); 
     } 
     return; 
    } 
#endif 
} 

Das ist nicht Ihre Frage zur Gestaltung Motivationen nicht beantworten, aber sie auch gefragt, warum CFRelease tut nicht auf NULL prüfen. Es überprüft und schlägt absichtlich fehl, wenn NULL als Parameter übergeben wird.

Meine persönliche Überzeugung ist Quinn ähnlich, dass die CF-Designer es als einen Programmierfehler empfanden, NULL zu übergeben.

7

All diese Funktionen sind Teil von verschiedenen APIs, die verschiedenen Konventionen in Bezug zu folgen NULL Handhabung:

  1. CFRelease ist Teil des Corefoundation C SDK, das nicht NULL Referenz als Argumente standardmäßig akzeptiert. Teil der C++ Bibliothek (libc++), die ermöglicht NULL Argumente
  2. [nil release] verwendet Objective-C
  3. free(NULL) ist ein Teil der C-Bibliothek (libc), die NULL Argument
  4. delete NULL erlaubt (die Dereferenzierungen von nil ermöglicht)

Ich denke, die SDK-Autoren CoreFoundation entschieden, konsistenter zu sein mit dem Rest von SDK und nicht mit ähnlicher Funktion in anderen SDKs.

+2

Für mich sagt diese Antwort ziemlich viel: CFRelease stürzt ab, weil CF so funktioniert. free (NULL) stürzt nicht ab, weil der C-Standard dies sagt. delete NULL stürzt nicht ab, weil der C++ - Standard dies sagt. Es beantwortet meine Frage nicht. Ich frage, warum der CF-SDK-Designer bewusst beschlossen hat, dass seine öffentlichen APIs das Programm einfach zum Absturz bringen. –

+0

Ohne einen CF-Designer direkt zu fragen (vorausgesetzt, sie können/werden Ihnen sagen, warum), spekulieren wir nur. Ich habe meine beste Vermutung in meiner Antwort dargelegt. –

+0

Wenn Sie eine Frage stellen, die nur von der Person beantwortet werden kann, die diese API geschrieben hat, warum nach SO fragen? Der Sinn von SO besteht darin, Fragen zu stellen, die von der Gemeinschaft zu verantworten sind. – smorgan

9

Guter Punkt, es scheint nicht viel Sinn auf den ersten Blick zu machen. Natürlich, die behavior is properly documented, aber es wäre nett, wenn es würde NULL anmutig behandeln. Beachten Sie, dass CFRetain und CFMakeCollectable (neu in 10.4, GC aktiviert in 10.5) das gleiche Verhalten zeigen. Ich bin nicht mit all den Motivationen vertraut, die es auf diese Weise entworfen haben, aber der Schwerpunkt lag wahrscheinlich eher auf der internen Konsistenz mit dem Rest des CoreFoundation-Frameworks.

Es ist schwierig/unmöglich zu wissen warum CF wurde so entworfen, es sei denn, Sie können einen der Designer fragen. Meine beste Vermutung ist, dass die Designer entschieden haben, dass das Übergeben von NULL für Speicherverwaltungsfunktionen (sollte?) Ein Programmierfehler sein sollte. Man könnte argumentieren, dass das Verursachen eines Absturzes bei NULL ein wünschenswertes "Fail-Fast" Verhalten ist, da Bugs, die fast sofort abstürzen, einfacher zu finden sind als Bugs, die stillschweigend nichts tun, statt wie erwartet. Persönlich bevorzuge ich die Do-Nothing-on-Null-Ansatz, aber ich denke, das ist das Leben ...

Angesichts der Tatsache, dass die API nicht ändern kann/wird, können Sie entweder für NULL testen oder umgehen das Problem Fall. Eine Option könnte darin bestehen, eine Inline-Funktion oder einen Makro zu definieren, der CFRelease nur für Nicht-NULL-Referenzen aufruft. In jedem Fall ist es wahrscheinlich am besten, in Ihrem Code explizit zu sein, um Verwirrung auf der Straße zu vermeiden.

+4

Beachten Sie, dass Quartz CGImageRelease und ähnliche NULL akzeptieren: "Diese Funktion entspricht CFRelease, außer dass es keinen Fehler verursacht, wenn der Bildparameter NULL ist." – IlDan

+0

Richtig, es wäre nett, aber das ist in CoreGraphics, nicht Core Foundation. Wenn CFRelease und Freunde in ** not ** crash geändert wurden, wenn sie NULL übergeben wurde, könnte dies zu unerwarteten Ergebnissen im bestehenden Code führen (obwohl hoffentlich niemand absichtlich so Abstürze verursacht) und CoreFoundation-Programmierer verwirren, die an das Verhalten gewöhnt sind. Trotzdem stimme ich dir zu. –

2

Sie können sich den Quellcode von CFReleaseProtector ansehen, um dieses Problem zu lösen (oder besser zu verstehen).

CFRelease nicht mehr Absturz auf NULL,

http://unsanity.org/archives/haxies/cfrelease_no_mo.php

Sie CFReleaseProtector.sit mit dem Kommandozeilen-Tool UNAR auspacken können (Teil des Unarchiver, siehe seine Google-Code-Download-Liste).

+0

Immer noch Absturz (iOS 9). –

Verwandte Themen