Convenient constructors in ARC

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Convenient constructors in ARC

    Ist man unter ARC gezwungen alloc-init (oder new *brrrr*) zu verwenden um ARC sinnvoll zu nutzen?
    Ich finde es doch unpraktisch denn die convenient constructors haben ja nicht umsonst den namen.

    ich dachte immer dass apple unter ARC die [x autorelease] einfach rauslässt? dem scheint aber nicht so zu sein.

    hier ein kleiner test mit dessen resultat ich eben nicht gerechnet hätte:

    Quellcode

    1. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    2. {
    3. sleep(3);
    4. int l = 1000 * 1000 * 30;
    5. {
    6. void *c = malloc(l);
    7. NSData *d = [[NSData alloc] initWithBytesNoCopy:c length:l freeWhenDone:YES];
    8. NSLog(@"d: %lu", d.length);
    9. sleep(1);
    10. }
    11. sleep(1);
    12. {
    13. void *c = malloc(l);
    14. NSData *d = [NSData dataWithBytesNoCopy:c length:l freeWhenDone:YES];
    15. NSLog(@"d: %lu", d.length);
    16. sleep(1);
    17. }
    18. sleep(10);
    19. }
    Alles anzeigen
    Dateien
    • mem-usage.png

      (14,07 kB, 162 mal heruntergeladen, zuletzt: )
  • Naja, in dem speziellen Fall wäre es sinnvoll den wiederkehrenden Teil in eine Funktion auszulagern.

    Aber offensichtlich funktionieren die Scopes mit den geschweiften Klammern nicht.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Marco Feltmann schrieb:

    Naja, in dem speziellen Fall wäre es sinnvoll den wiederkehrenden Teil in eine Funktion auszulagern.

    Aber offensichtlich funktionieren die Scopes mit den geschweiften Klammern nicht.


    nein das hat mit eigener funktion oder scope nichts zu tun sondern damit dass da wohl doch noch irgendwie in den arp reingefeuert wird anstatt ganz auf ARC zu vertrauen. meine frage ist: warum ist das so? und sollte man deshab auf die convenience-allocatoren verzichten obwohl sie doch so praktisch sind?
  • gandhi schrieb:

    gritsch schrieb:

    warum ist das so? und sollte man deshab auf die convenience-allocatoren verzichten obwohl sie doch so praktisch sind?


    Vermutung: Zwecks Kompatibilität mit MRC-Code zur Laufzeit (z.B. eine Lib, die Du verwendest)?

    Und, nein, ich verzichte nicht auf convenience-allocatoren.

    schönen Gruß

    gandhi


    und das kann man nicht zur laufzeit abfragen oder ist das dann ein timing-problem (ärger als der ARP an sich)
  • gritsch schrieb:

    Ist man unter ARC gezwungen alloc-init (oder new *brrrr*) zu verwenden um ARC sinnvoll zu nutzen?


    Quatsch.

    gritsch schrieb:


    hier ein kleiner test mit dessen resultat ich eben nicht gerechnet hätte:

    Quellcode

    1. NSData *d = [[NSData alloc] initWithBytesNoCopy:c length:l freeWhenDone:YES];


    Methode beginnt mit “alloc” -> Dein Code hat die Object ownership.

    gritsch schrieb:

    hier ein kleiner test mit dessen resultat ich eben nicht gerechnet hätte:

    Quellcode

    1. NSData *d = [NSData dataWithBytesNoCopy:c length:l freeWhenDone:YES];


    Methode beginnt mit “data” -> Dein Code hat keine Object ownership, das Objekt landet auf dem Autorelease Pool.

    Basic Memory Management Rules, sollte eigentlich jeder kennen. Hat nichts mit ARC zu tun.
  • SteveJ schrieb:

    gritsch schrieb:

    Ist man unter ARC gezwungen alloc-init (oder new *brrrr*) zu verwenden um ARC sinnvoll zu nutzen?


    Quatsch.

    gritsch schrieb:


    hier ein kleiner test mit dessen resultat ich eben nicht gerechnet hätte:

    Quellcode

    1. NSData *d = [[NSData alloc] initWithBytesNoCopy:c length:l freeWhenDone:YES];


    Methode beginnt mit “alloc” -> Dein Code hat die Object ownership.

    gritsch schrieb:

    hier ein kleiner test mit dessen resultat ich eben nicht gerechnet hätte:

    Quellcode

    1. NSData *d = [NSData dataWithBytesNoCopy:c length:l freeWhenDone:YES];


    Methode beginnt mit “data” -> Dein Code hat keine Object ownership, das Objekt landet auf dem Autorelease Pool.

    Basic Memory Management Rules, sollte eigentlich jeder kennen. Hat nichts mit ARC zu tun.


    ist mir klar, aber warum sollte man den ARP verwenden und somit viel speicher blockieren wenn es schon ARC gibt?
  • gritsch schrieb:

    SteveJ schrieb:

    Basic Memory Management Rules, sollte eigentlich jeder kennen. Hat nichts mit ARC zu tun.


    ist mir klar, aber warum sollte man den ARP verwenden und somit viel speicher blockieren wenn es schon ARC gibt?


    Wenn Dir das klar ist, dann verstehe ich Deine Frage nicht. Was genau hat das mit ARC zu tun? ARC ersetzt einfach die händische Zählung, weil der Compiler das besser als du kann. Vielleicht solltest Du “Transitioning to ARC” noch mal lesen?

    Transitioning to ARC schrieb:

    Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide) by adding the appropriate memory management calls for you.

  • SteveJ schrieb:

    gritsch schrieb:

    SteveJ schrieb:

    Basic Memory Management Rules, sollte eigentlich jeder kennen. Hat nichts mit ARC zu tun.


    ist mir klar, aber warum sollte man den ARP verwenden und somit viel speicher blockieren wenn es schon ARC gibt?


    Wenn Dir das klar ist, dann verstehe ich Deine Frage nicht. Was genau hat das mit ARC zu tun? ARC ersetzt einfach die händische Zählung, weil der Compiler das besser als du kann.


    nein der compiler kann es nicht besser als ich. der compiler kann es besser als viele (vor allem einsteiger) und ab und zu mal besser wie ich aber wenn ich es fehlerfrei mache dann kann ich es besser als der compiler ;)

    dass es der compiler aber besser kann als der ARP das glaube ich gerne. und genau deshalb dachte ich dass der ARP so gut wie nicht mehr genutzt wird. In meinem naiven glauben dachte ich dass apple einfach in der implementierung von "autorelease" abfragt ob es sich in einem ARC-environment befindet udn dann einfach "return self;" aufruft und andernfalls (MRC) eben sich wie bisher in den ARP packt...
  • gritsch schrieb:

    nein der compiler kann es nicht besser als ich. der compiler kann es besser als viele (vor allem einsteiger) und ab und zu mal besser wie ich aber wenn ich es fehlerfrei mache dann kann ich es besser als der compiler ;)


    Wenn du es fehlerfrei machst, kannst du es genau so gut wie der Compiler. Da ich vermute, dass du nicht fehlerfrei bist, kannst du es schlechter als der Compiler.

    gritsch schrieb:

    dass es der compiler aber besser kann als der ARP das glaube ich gerne.


    Das kannst du gerne glauben, das ist aber leider Blödsinn. Der Satz ergibt keine Sinn.

    gritsch schrieb:

    In meinem naiven glauben dachte ich dass apple einfach in der implementierung von "autorelease" abfragt ob es sich in einem ARC-environment befindet udn dann einfach "return self;" aufruft und andernfalls (MRC) eben sich wie bisher in den ARP packt...


    Wie oben: Dokumentation lesen hilft:

    SteveJ schrieb:

    Transitioning to ARC schrieb:

    Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide) by adding the appropriate memory management calls for you.
  • SteveJ schrieb:

    gritsch schrieb:

    nein der compiler kann es nicht besser als ich. der compiler kann es besser als viele (vor allem einsteiger) und ab und zu mal besser wie ich aber wenn ich es fehlerfrei mache dann kann ich es besser als der compiler ;)


    Wenn du es fehlerfrei machst, kannst du es genau so gut wie der Compiler. Da ich vermute, dass du nicht fehlerfrei bist, kannst du es schlechter als der Compiler.

    gritsch schrieb:

    dass es der compiler aber besser kann als der ARP das glaube ich gerne.


    Das kannst du gerne glauben, das ist aber leider Blödsinn. Der Satz ergibt keine Sinn.

    gritsch schrieb:

    In meinem naiven glauben dachte ich dass apple einfach in der implementierung von "autorelease" abfragt ob es sich in einem ARC-environment befindet udn dann einfach "return self;" aufruft und andernfalls (MRC) eben sich wie bisher in den ARP packt...


    Wie oben: Dokumentation lesen hilft:

    SteveJ schrieb:

    Transitioning to ARC schrieb:

    Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide) by adding the appropriate memory management calls for you.


    1. bitte nicht ARC und ARP verwechseln.

    2. nein, wenn ichs richtig mache dann kann ichs besser als der compiler weil ich überflüssige retain und releases einsparen kann (das steht auch selbst bei apple in der doku so).

    3. der satz ergibt sinn weil ich mit dem compiler eben ARC gemeint habe und der ist meiner meinung nach besser als ARP - also doch nicht sinnfrei oder?

    4. und wieder verwechselt du ARC und ARP. klar nimmt ARC das ab wenn man alloc-init verwendet, aber eben nicht wenn man einen convenience-constructor verwendet weil dann das zeug anscheinend im ARP (nicht ARC) landet!
  • Noch eine Anmerkung.
    Class *d = [Class convinientConstructor];
    führt nicht dazu dass es es immer im ARP landet.
    ARC weiss dass das Object nicht mehr gebraucht wird und dealloziert es bereits als wäre es mit alloc init erzeugt.
    Das Gleiche gilt für Objekte die autoreleased von einer Methode zurückgegeben werden.
    Der ARP wird interessant wenn Bibliotheken verwendet werden die noch kein ARC verwenden.
    Würde aller Code ARC verwenden, wäre der der ARP überflüssig.

    Zu Deinem Beispiel würde ich sagen NSData dataWithBytesNoCopy ist noch nicht auf ARC umgestellt (-;
  • sauerzapf schrieb:

    Noch eine Anmerkung.
    Zu Deinem Beispiel würde ich sagen NSData dataWithBytesNoCopy ist noch nicht auf ARC umgestellt (-;


    das klingt jetzt schon ganz anderns. habe das ganze also mit einer etwas weniger "speziellen" methode getestet aber es landet wieder im ARP:

    Quellcode

    1. ​- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    2. {
    3. // create file: mkfile -v 30M ~/testdata.dat
    4. NSString *path = [@"~/testdata.dat" stringByExpandingTildeInPath];
    5. sleep(3);
    6. //int l = 1000 * 1000 * 30;
    7. {
    8. //void *c = malloc(l);
    9. //NSData *d = [[NSData alloc] initWithBytesNoCopy:c length:l freeWhenDone:YES];
    10. NSData *d = [[NSData alloc] initWithContentsOfFile:path];
    11. NSLog(@"d: %lu", d.length);
    12. sleep(1);
    13. }
    14. sleep(1);
    15. {
    16. //void *c = malloc(l);
    17. //NSData *d = [NSData dataWithBytesNoCopy:c length:l freeWhenDone:YES];
    18. NSData *d = [NSData dataWithContentsOfFile:path];
    19. NSLog(@"d: %lu", d.length);
    20. sleep(1);
    21. }
    22. sleep(10);
    23. }
    Alles anzeigen
  • das ganze jetzt nochmal mit NSMutableString getestet und wieder das gleiche verhalten. das kann doch nicht sein dass die "großen" klassen nicht ARC-fähig sind, andere aber schon?

    Quellcode

    1. ​- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    2. {
    3. // create file: mkfile -v 30M ~/testdata.dat
    4. //NSString *path = [@"~/testdata.dat" stringByExpandingTildeInPath];
    5. int l = 1000 * 1000 * 30;
    6. NSMutableString *originalString = [NSMutableString stringWithCapacity:l];
    7. for (int i = 0; i < l; i++) [originalString appendString:@"X"];
    8. sleep(3);
    9. {
    10. //void *c = malloc(l);
    11. //NSData *d = [[NSData alloc] initWithBytesNoCopy:c length:l freeWhenDone:YES];
    12. //NSData *d = [[NSData alloc] initWithContentsOfFile:path];
    13. NSMutableString *d = [[NSMutableString alloc] initWithString:originalString];
    14. NSLog(@"d: %lu", d.length);
    15. sleep(1);
    16. }
    17. sleep(1);
    18. {
    19. //void *c = malloc(l);
    20. //NSData *d = [NSData dataWithBytesNoCopy:c length:l freeWhenDone:YES];
    21. //NSData *d = [NSData dataWithContentsOfFile:path];
    22. NSMutableString *d = [NSMutableString stringWithString:originalString];
    23. NSLog(@"d: %lu", d.length);
    24. sleep(1);
    25. }
    26. sleep(10);
    27. }
    Alles anzeigen
  • gritsch schrieb:

    Wie oben: Dokumentation lesen hilft:

    SteveJ schrieb:

    Transitioning to ARC schrieb:

    Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide) by adding the appropriate memory management calls for you.


    1. bitte nicht ARC und ARP verwechseln.


    Keine Sorge, die Dokumentation ist von Apple, die kriegen das schon hin. ;)

    gritsch schrieb:

    2. nein, wenn ichs richtig mache dann kann ichs besser als der compiler weil ich überflüssige retain und releases einsparen kann (das steht auch selbst bei apple in der doku so).


    Ah. Quelle? Aber wegen mir, viel Spaß.

    gritsch schrieb:

    3. der satz ergibt sinn weil ich mit dem compiler eben ARC gemeint habe und der ist meiner meinung nach besser als ARP - also doch nicht sinnfrei oder?


    Mir ist nicht klar wie etwas das etwas anderes benutzt besser sein kann. Das ist ungefähr als würdest du sagen ein Auto sei besser als seine Räder. Ich würde sagen sehr sinnfrei.

    Oder meinst Du ARC mit Autorelease Pools ist besser als händische Referenzzählung mit Autorelease Pools? Dann ja. Andererseits behauptest Du ja oben, händische Referenzzählung wäre besser...

    gritsch schrieb:

    4. und wieder verwechselt du ARC und ARP. klar nimmt ARC das ab wenn man alloc-init verwendet, aber eben nicht wenn man einen convenience-constructor verwendet weil dann das zeug anscheinend im ARP (nicht ARC) landet!


    Hä?

    SteveJ schrieb:

    Basic Memory Management Rules, sollte eigentlich jeder kennen. Hat nichts mit ARC zu tun.


    Wie oben. Convenience Constructors beginnen nicht mit “alloc”, “new”, “copy”, oder “mutableCopy”, also packen sie das Resultat sinnvollerweise auf den Autorelease Pool, wenn sie kein Singleton zurückgeben. Oder sie haben ein Objektcache, auch denkbar. Was genau ist da jetzt das Problem?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von SteveJ ()

  • Mache mal einen eigenen Convenient Constructor.

    CLANG Docu: Unretained return values.
    A method or function which returns a retainable object type but does not return a retained value must ensure that the object is still valid across the return boundary.

    When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary.
    In the worst case, this may involve an autorelease, but callers must not assume that the value is actually in the autorelease pool.

    ARC performs no extra mandatory work on the caller side, although it may elect to do something to shorten the lifetime of the returned value.

    Reallife->
    For these getter methods, the compiler generates objc runtime functions on both sides (caller and callee).
    The callee runtime function looks up the call stack and looks for the caller runtime function. If it finds it, the caller is running ARC code and the callee does not autorelease, otherwise it autoreleases.
  • …ich würde ja sagen, dass das alles egal ist, da der ARC sich eher wenig um eure sleeps kümmert sonder nur aufräumt wenn dem 'd' ein neuer wert zugewiesen wird… bzw anderweitig die referenz erlischt...

    Edit:
    …Lesbarkeit - keine Ahnung warum beim schreiben auf dem Telefon das so ein html Kauderwelsch geworden ist.
    snafu
    :() { :|: &};:
    sometimes i dream in hex
    Obey gravity! Because its a law!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von chartus ()