Dies ist nichts anderes als eine wilde Vermutung, aber versuchen Sie Ändern/Hinzufügen dieses:
[iStream open];
[oStream open];
CFRetain(self);
}
Dies ist nur für Testzwecke ist, und Sie werden wahrscheinlich ‚Leck‘ self
als Ergebnis. Ich begründe diese Empfehlung, weil die Stack-Trace während irgendeiner Art von Callback-Verarbeitung abstürzt, und Sie sich selbst als den Delegaten festgelegt haben, so dass das Callback-Ziel Sie sind.
Wenn das Problem "behebt", dann habe ich keine Ahnung, was das Problem ist (seltsam wie es klingt).
BEGIN EDIT
Würden Sie es nicht wissen, gleich nachdem ich die Antwort geschrieben, ich glaube, ich habe das Problem gefunden. Nehmen Sie die folgende Änderung (mit Angabe der CFRetain
Bit nicht hinzugefügt werden):
[NSStream getStreamsToHost:host port:1234 inputStream:&iStream outputStream:&oStream];
iStream = iStream;
oStream = oStream;
WICHTIG: beide iStream
und oStream
müssen ivars, Teil Ihrer Klassendeklaration sein. Da das Code-Snippet, das du gepostet hast, dies als eine Möglichkeit offen lässt, dachte ich nur, dass es klar wäre.
Wenn sein die Fehler, den ich denke, es ist, ich sei bereit, diese ‚Korrekturen‘ zu, das Problem zu setzen:
iStream = self;
oStream = self;
[NSStream getStreamsToHost:host port:1234 inputStream:&iStream outputStream:&oStream];
Vorausgesetzt, das ist, was ich denke, es ist, sollten Sie in der Lage sein, zu entfernen die Korrekturen, fügen Sie etwas wie NSLog(@"self is: %p, iStream is: %p, oStream is: %p", self, iStream, oStream)
hinzu und warten Sie dann, bis es abstürzt. Dann wird in den Debugger, geben Sie so etwas wie:
gdb> p *(MySelfClass *)0xdeadbeef
Wo MySelfClass
ist Ihr Klassennamen und 0xdeadbeef
ist, was auch immer der Zeiger für self
ist. Die Werte für iStream
und oStream
sollten identisch sein mit NSLog
Ausspucken. Geben Sie dann in
gdb> info gc-references 0xPTR
gdb> info gc-roots 0xPTR
Für jede self
, iStream
, oStream
. Ich denke, Sie werden feststellen, dass das einzige System, das dem GC-System bekannt ist, self
ist, trotz der Tatsache, dass Ihre Ivars Zeiger haben.
Ein weiteres extrem frustrierendes Problem, das ich bei der Verwendung von Cocoa GC-System hatte, ist der Compiler erzeugt fehlerhaften Code für __strong
Zeiger (Ich habe mehrere Bugs in diesem Zusammenhang eingereicht). Meistens verursacht dies keinen Absturz, da das Problem durch einen anderen Live-Zeiger maskiert wird, was durch die Tatsache verschlimmert wird, dass beide Zeiger in 99% der Fälle dazu neigen, nahezu gleichzeitig zu "sterben". Das GC-System führt nur einige Male pro Sekunde eine Sammlung durch, aber meistens weniger häufig.
Dann gibt es die Zeiten, wo es keinen anderen Zeiger gibt, um den Compilerfehler zu maskieren. Dies ist ein perfektes Beispiel: Sie benötigen diese Zeiger, um mehrere Durchlauf-Schleifeniterationen zu überstehen. In diesen Fällen werden Sie schließlich irgendwann mit einem Sammlungslauf über die Pfade gehen. Wenn das passiert, ist es völlig zufällig, es könnte mehrmals pro Sekunde oder einmal pro Minute sein.
END EDIT
Es gibt eine zweite 'Lösung' für Ihr Problem: Verwenden GC nicht. In der Tat, ich empfehle dies dringend, und das kommt aus der praktischen Erfahrung mit diesem GC-System seit 10.5 Beta in der realen Welt, nicht-triviale Programme. Ein Grund, warum ich seine Verwendung ablehne, ist rein pragmatisch: Während das Debugging von manueller Speicherverwaltung/Referenz-Zählung schwierig sein kann und Zeitverschwendung ist, ist es praktisch unmöglich, GC-Probleme zu debuggen. Ich würde jeden Geldbetrag wetten, auf den dein Problem hinausläuft: Es ist im Wesentlichen ein Multithread-Race-Condition-Bug. Dies ist die am schwierigsten zu debuggende Klasse von Problemen.
Meine Vermutung ist, wo einige, etwas, was die __strong
Qualifier auf einen GC verwalteten Zeiger gesunken ist, und der größte Täter ist ein NSObject *object;
zu einem void *pointer;
, wie pointer = object;
. Der Compiler lässt Sie dies ohne eine Warnung tun, obwohl es zu den Arten von Problemen führt, die Sie haben, und ist fast immer ein Fehler, oder öffnet das Potenzial für diese Art von Fehlern. Manchmal ist es nicht einmal offensichtlich, dass Sie dies getan haben, z. B. wenn Sie ein Objekt an ein Argument übergeben, das den Typ void *
annimmt. Am schlimmsten ist, dass Sie im letzten Fall nichts mehr tun können: Die Methode oder Funktion wurde nicht so kompiliert, dass der empfangene Zeiger als __strong
behandelt wird.
Es gibt keine generische Methode, wie Sie diese Fälle korrekt behandeln können, damit sich Ihr Programm deterministisch verhält und nicht abstürzt. Es könnte buchstäblich nicht einmal ein Weg sein. Wenn Sie unweigerlich auf einen dieser Fälle stoßen, die viel häufiger sind, als Sie denken, oder das Problem selbst vergessen, indem Sie __strong
vergessen, verspreche ich Ihnen, dass alle "Gewinne" in der Produktivität, die Ihnen mit GC versprochen wurden, gelöscht werden hinaus, zu dem Punkt, wo GC nicht verwendet worden wäre, wäre sowohl viel schneller als auch viel einfacher gewesen.
Das nächste Problem, auf das ich stieß, sind Leistungsprobleme. Im Bereich von zwei bis fünf mal langsamer. Dies liegt daran, dass dem GC-System mitgeteilt werden muss, wenn ein GC-Manager-Zeiger irgendwo auf dem Heap gespeichert ist. Dies ist normalerweise nur ein einzelner Befehl, aber der Compiler schreibt die Zuweisung erneut in einen Funktionsaufruf objc_assign_strongCast()
(!), Der immer eine globale GC-Mutex-Sperre (!!) annimmt. Dies ist eine schockierend teure Operation.
Dies ist eine ziemlich häretische Empfehlung und ich bin mir ziemlich sicher, dass dies Cocoa GC Apologeten in Scharen hervorbringen wird.Die Argumente im Grunde laufen auf:
Apples testing showed that for real world applications there was no performance impact.
Dies ist keine Verteidigung ist, und es kommt fast immer von einem Apple-Mitarbeiter. In keiner Weise adressiert, negiert oder behebt dieser Anspruch die Leistungsprobleme meiner real world app
. Und nach akademischen Maßstäben kann dieser Anspruch nicht einmal ernst genommen werden, es sei denn, Sie sind bereit, die Daten und Methoden zur Verfügung zu stellen, mit denen ich die gleichen Ergebnisse überprüfen und reproduzieren kann.
Lots of real world applications use GC.... like Xcode!
In aller Ehrlichkeit, haben die einzige Anwendung, die ich je ist Xcode erwähnt gesehen. Eines Tages (vor nicht allzu langer Zeit) habe ich mir die Mühe gemacht, den ganzen GC mit Apps auf meinem Rechner zu finden. Es gab zwei Apps: Xcode.app
und /Developer/Applications/Utilities/Property List Editor.app/
. Dies beinhaltet alle Apps von Drittanbietern, die ich hatte, zusammen mit den Entwicklertools (natürlich), Standard OS X-Sachen, iLife und iWork '09. Abgesehen von der Tatsache, dass es sich hierbei nicht um ein korrektes Beispiel für die Verwendung von GC durch Dritte handelt, gibt es etwas sehr Interessantes, das zunächst nicht offensichtlich ist: Es gibt sehr viele Apple-Anwendungen, die dies abdecken, und es gibt genau eine real world app
: Xcode.app
.
Dies wird umso interessanter durch die Tatsache, dass Apple anscheinend in Haustests durchgeführt hat, um GC Auswirkungen auf die Leistung zu bestimmen. Ich denke, es ist sicher zu sagen, dass die Apps, die abgedeckt werden, einige der höchsten auf der Liste sein werden, um zu sehen, ob GC irgendwelche Auswirkungen auf die Apps hat. Dies bedeutet, dass entweder Apple die Konvertierung einiger dieser Apps in GC vorgenommen hat und dann entschieden hat, die GC-Version nicht zu versenden (was sofort die Frage aufwirft, warum nicht), oder dass es berechtigte Zweifel darüber aufkommen lässt, wie viele reale Welten es gibt Apps wurden verwendet.
Verwenden Sie NSZombieEnabled. http://developer.apple.com/technotes/tn2004/tn2124.html –
Probieren Sie es aus, es gibt keinerlei Informationen. Danke trotzdem. –
Es nicht? Sie erhalten keine Meldung "Nachricht an freigegebene Instanz gesendet"? –