Reference-counted object is used after it is released

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

  • Reference-counted object is used after it is released

    Hi!

    Ich habe eben den Static Analyzer über meinen Code laufen lassen und habe bei jedem Vorkommen von folgendem Konstrukt den Fehler "Reference-counted object is used after it is released" bekommen.

    Quellcode

    1. NSString* myNSString = [self methodeDieEinenNSStringZurueckGibt];
    2. if ([myNSString length] != 10) return nil;


    Der Code funktioniert einwandfrei, nur was will mir der Analyzer mit der Meldung sagen?

    Gruß!
  • myNSString ist nur ein Pointer und keine konkrete Instanz?

    Falls der String in

    Quellcode

    1. [self methodeDieEinenNSStringZurueckGibt];

    erzeugt wird, wird er da auch wieder released. Wenn Du Pech hast, ehe Deine Abfrage durchlaufen wird.

    Erzeug Dir mal eine konkrete Instanz und schau ob er immer noch meckert.
    NSString* myNSString = [[NSString alloc] initWithString:<deinString>];
  • Hm, das ist ja lustig. Das heißt, dass der Code oben eigentlich nur funktioniert, weil der String zu langsam released wird?
    Ich dachte, es wird beim return automatisch eine Kopie erzeugt oder zumindest ein retain auf den in der Methode erstellten String gemacht.

    Auf jeden Fall meckert der Analyzer nicht mehr rum, wenn ich in
    [self methodeDieEinenNSStringZurueckGibt];
    ein
    return [returnString copy];
    mache.

    Edit: Jetzt kommt der Fehler bei return [returnString copy]; :whistling:

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

  • Schon klar, ich verstehe nur das Problem des Analyzers nicht.
    Wenn ich in einer Methode einen NSString erzeuge und den zurückgeben möchte, hab ich den immer bisher einfach mit return zurück gegeben und mit einem NSString *newString = [self method]; aufgenommen.
    Laut Analyzer ist das ja grundlegend falsch, aber ich verstehe nicht warum.
    M.E. sollte beim zurückgeben das NSString Objekt nicht released werden.
  • *Huch* Das meckert der inzwischen als Standard an!?

    Das ist ein Pattern, welches man immer benutzt hat, was aber eigentlich fehlerhaft ist. Die Methode garantiert nur die Rückgabe einer gültigen Referenz, nicht deren weiteren Verlauf. Insbesondere ist das, was Hillegas gesagt hat, nämlich, dass man es als autoreleased betrachten soll, völliger Blödsinn. Daher müsste man es eigentlich in der Anweisung, die es liefert, ein retain machen, welches man balanciert. Macht aber kein Mensch.

    Das wird aber sicherlich nicht in der Allgemeinheit angemeckert. Dann wäre zu viel Code broken, weil es wie gesagt ein Standardpattern ist (aka Speicherverwaltung aus dem unteren Rückenmark). Da muss noch ein Effekt hinzukommen. Mischst du vielleicht ARC mit MRC?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Die Meldung kommt anscheinend auch nur, wenn ich den NSString aus einem CFTypeRef bridge.
    Hier mal ein Beispiel:

    Quellcode

    1. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    2. {
    3. // Insert code here to initialize your application
    4. NSString *ioPlatformSerialString;
    5. ioPlatformSerialString = [self ioPlatformSerial];
    6. NSLog(@"%@",ioPlatformSerialString);
    7. }
    8. -(NSString*)ioPlatformSerial {
    9. io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,IOServiceMatching("IOPlatformExpertDevice"));
    10. if (platformExpert) {
    11. NSString *serialNumber;
    12. CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,CFSTR(kIOPlatformSerialNumberKey),kCFAllocatorDefault, 0);
    13. IOObjectRelease(platformExpert);
    14. if (serialNumberAsCFString) {
    15. serialNumber = (__bridge NSString *)(serialNumberAsCFString);
    16. CFRelease(serialNumberAsCFString);
    17. return serialNumber;
    18. }
    19. }
    20. return nil;
    21. }
    Alles anzeigen
  • bananenBrot schrieb:

    Die Meldung kommt anscheinend auch nur, wenn ich den NSString aus einem CFTypeRef bridge.

    Das erklärt es ja. __bridge transferiert keine Ownership und du released den String, bevor du ihn zurück gibst. Hier musst du __bridge_transfer nehmen.

    Quellcode

    1. -(NSString*)ioPlatformSerial {
    2. io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,IOServiceMatching("IOPlatformExpertDevice"));
    3. if (platformExpert) {
    4. NSString *serialNumber;
    5. CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,CFSTR(kIOPlatformSerialNumberKey),kCFAllocatorDefault, 0);
    6. IOObjectRelease(platformExpert);
    7. if (serialNumberAsCFString) {
    8. serialNumber = (__bridge_transfer NSString *)(serialNumberAsCFString);
    9. return serialNumber;
    10. }
    11. }
    12. return nil;
    13. }
    Alles anzeigen

    Dann ist auch der Analyzer zufrieden.