*nix Programme ansprechen?

  • Original von Squart
    Original von MetalSnake
    -(uin32_t)calcCRC32FromFile:(NSString*)inFilename;
    Anscheinend hast du ein t vergessen (uint32_t)


    Oups 8o - sorry ;)

    Squart, Dank Dir für den Tipp! - Hab den Snippet auch schon entsprechend korrigiert! :rolleyes:
  • Original von MetalSnake
    ah, hatte nur copy und paste benutzt.


    Jau Sorry und Danke! - War mein Tippfehler ;)

    klappt jetzt scheinbar, aber welches Polynom muss ich denn da jetzt übergeben um die gleichen Werte wie cksum -o 3 zu bekommen?


    Hallo MetalSnake,

    der Startwert von 0, wie in meinem Snippet angegeben, liefert genau das selbe Ergebnis wie cksum -o3. Der CRC32 Algorithmus arbeitet "fest verdrahtet" mit einem Polynom G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

    Das liegt in der "Natur" des CRC32, denn so ist er definiert.

    Wenn Du mal man cksum im Terminal eingibst, dann steht da, dass die Option -o3 beim cksum eben eine klassische CRC32 ergibt. Und die ist eben durch den oben genannten Polynom definiert.

    Beachte bitte, dass cksum die Checksum als Dezimalzahl ausgibt. Wenn Du die Werte mit dem crc32 der Zlib auf selber Zahlenbasis mit der von csum -o3 vergleichst, wirst Du sehen, dass diese exakt übereinstimmen.

    Viel Spass - James -
  • Ich sag ja, die Berechnung ist mir zu hoch.
    Verstehe dann nicht so wirklich wofür man ein Polynom übergeben kann wenn sowieso immer der selbe benutze wird?

    Naja jedenfalls hatte ich vorhin unterschiedliche Werte, aber das lag daran dass ich bei der Ausgabe %qi benutzt habe statt %u, erstes habe ich in der Methode mit dem cksum Aufruf benutzt da ich irgendwie auf einen gemeinsamen nenner kommen musste mit dem NSScanner bei dem ich keine Methode gefunden habe um in ein unsignedInt zu scannen, aber in longlong geht also habe ich den benutzt. Aber ich wie gerade sehe scheint es doch zu gehen wenn ich vorher (unsigned *) schreibe, habs aber noch nicht ausprobiert.
    Ist mir im Moment auch nicht mehr so wichtig. Die Methode mit der zlib scheint jetzt nach einem ersten Test 200ms schneller zu sein. :)

    Wollte grad mal beide Methoden jeweils 2500 mal in einer Schleife durchlaufen lassen. nach 2 Minuten ging hier gar nichts mehr, 10 Minuten später kam dann endlich die Erlösung mit diesem Fehler:

    Quellcode

    1. SnakeRom(21473,0xa000ef98) malloc: *** vm_allocate(size=4194304) failed (error code=3)
    2. SnakeRom(21473,0xa000ef98) malloc: *** error: can't allocate region

    Sind dass die Auswirkungen eines Speicherlecks?
    Der war übrigens mit der ersten Schleife (die benutzt die zlib) noch nicht fertig.

    Jedenfalls mal ganz lustig seinen Rechner mit seinem eigenen Code in die Knie zu zwingen. ;)
  • Original von MetalSnake
    Aber ich wie gerade sehe scheint es doch zu gehen wenn ich vorher (unsigned *) schreibe, habs aber noch nicht ausprobiert.

    Hmm, da waere ich vorsichtig. Was erwartet den die Funktion, einen Zeiger oder einen Wert?
    (unsigned int) und einen Zeiger dauf man normal nicht ohne weiteres austauschen.
    Original von MetalSnake
    Wollte grad mal beide Methoden jeweils 2500 mal in einer Schleife durchlaufen lassen. nach 2 Minuten ging hier gar nichts mehr, 10 Minuten später kam dann endlich die Erlösung mit diesem Fehler:

    Quellcode

    1. SnakeRom(21473,0xa000ef98) malloc: *** vm_allocate(size=4194304) failed (error code=3)
    2. SnakeRom(21473,0xa000ef98) malloc: *** error: can't allocate region

    Sind dass die Auswirkungen eines Speicherlecks?
    Der war übrigens mit der ersten Schleife (die benutzt die zlib) noch nicht fertig.

    Jedenfalls mal ganz lustig seinen Rechner mit seinem eigenen Code in die Knie zu zwingen. ;)

    Ja, irgendwo hast Du da ein Speicherleck. free()s und -releases: nicht vergessen. :D

    Manfred
  • Original von asrael
    [Hmm, da waere ich vorsichtig. Was erwartet den die Funktion, einen Zeiger oder einen Wert?
    (unsigned int) und einen Zeiger dauf man normal nicht ohne weiteres austauschen.

    Ach, hab mich verguckt:

    - (BOOL)scanHexInt:(unsigned *)intValue

    damit gehen dann wohl nur hex Zahlen die in einem unsigned int gespeichert werden? Jedenfalls für mich an dieser stelle damit unbrauchbar, da die CRC werte ja als dezimal Zahl ausgegeben werden.

    Original von asrael

    Ja, irgendwo hast Du da ein Speicherleck. free()s und -releases: nicht vergessen. :D

    Manfred

    Tja, damit habe ich mich noch nicht wirklich auseinander gesetzt, sollte ich jetzt vielleicht mal tun. ;)
  • Vorsicht vor wuchernden Speicherallozierungen!

    Original von MetalSnake
    Ich sag ja, die Berechnung ist mir zu hoch.
    Verstehe dann nicht so wirklich wofür man ein Polynom übergeben kann wenn sowieso immer der selbe benutze wird?


    Hallo MetalSnake,

    Sorry - war mein Fehler - der erste Parameter beim crc32() ist ein "Startwert" und definiert *nicht* den Polynom, denn der ist ja wie gesagt durch den CRC32 bereits vorgegeben.

    Normalerweise ist dieser Wert 0. Es gibt aber auch Fälle, bei denen von anderen Startwerten ausgegangen wird. Werden DVB-Sections berechnet gilt hier ein anderer Wert.

    So kannst Du auch selbst einen eigenen Startwert vorgeben um die Berechnung ganz bewusst von der einer "standard CRC32 abweichen zu lassen. Nimmst Du aber den Wert 0, so korrelliert der zurückgegebene CRC32 exakt mit dem eines cksum -o 3.

    Naja jedenfalls hatte ich vorhin unterschiedliche Werte, aber das lag daran dass ich bei der Ausgabe %qi benutzt habe statt %u, erstes habe ich in der Methode mit dem cksum Aufruf benutzt da ich irgendwie auf einen gemeinsamen nenner kommen musste mit dem NSScanner bei dem ich keine Methode gefunden habe um in ein unsignedInt zu scannen, aber in longlong geht also habe ich den benutzt. Aber ich wie gerade sehe scheint es doch zu gehen wenn ich vorher (unsigned *) schreibe, habs aber noch nicht ausprobiert.
    Ist mir im Moment auch nicht mehr so wichtig. Die Methode mit der zlib scheint jetzt nach einem ersten Test 200ms schneller zu sein. :)


    Freilich ist sie schneller, denn der Weg mit dem Kommandozeilenskripten ist ja viel Aufwendiger. Es muss erst ein Thread erzeugt werden, dann werden die Ausgaben durch eine Pipe gejagt, etc. ...

    Mich verblüfft, dass ein einziger Aufruf schon 200 ms bringt! - Das ist ja für eine schnelle CPU eine halbe Ewigkeit.

    Wenn Du nun diese CRC32 Berechnung sehr oft im Programm durchführst, dann lohnt sich ein Libcall über den crc32 der zlib sehr, sehr schnell.

    Wollte grad mal beide Methoden jeweils 2500 mal in einer Schleife durchlaufen lassen. nach 2 Minuten ging hier gar nichts mehr, 10 Minuten später kam dann endlich die Erlösung mit diesem Fehler:

    Quellcode

    1. SnakeRom(21473,0xa000ef98) malloc: *** vm_allocate(size=4194304) failed (error code=3)
    2. SnakeRom(21473,0xa000ef98) malloc: *** error: can't allocate region

    Sind dass die Auswirkungen eines Speicherlecks?
    Der war übrigens mit der ersten Schleife (die benutzt die zlib) noch nicht fertig.

    Jedenfalls mal ganz lustig seinen Rechner mit seinem eigenen Code in die Knie zu zwingen. ;)


    Hast Du den Code exakt so, wie ich ihn Dir gepostet habe exakt so laufen lassen? Dann ist die Sache nämlich klar - war ehrlich gesagt nicht ganz sauber designed von mir - eher etwas "konservativ" ;)

    Denn - Deine Fehlermeldung zeigt mir, daß Dir der Speicher ausgeht. Und dass das so lange dauert liegt garantiert auch daran, dass die Kiste ordentlich Swapt, bis sie die Grätsche macht. Oh, da wird dann aber ne Menge Speicher angefordert. So eine Swap-Partition ist schon ordentlich gross! 8o

    Woran das liegt ist klar, das schreibe ich nach dem nächsten Absatz, zuvor aber noch das:

    Die Geschwindigkeit hängt aber auch massgeblich auch davon ab, wie gross das File ist, über welches Du die CRC berechnen lässt. Dabei gibt weniger die Berechnung selbst den Ausschlag als vielmehr das Einlesen des Files, also die IO-Performanche, denn Du musst Das File ja *komplett* einlesen um die CRC zu berechnen. Entsprechend gross wird dann auch das NSData-Objekt Speicher reservieren.

    So, nun mal zu dem Thema, warum Dir der Speicher ausgeht:

    Wenn Du also ein fettes File von sagen wir mal 40 MByte einliest, wird Dir das NSData-Objekt "mehr oder weniger" kurzzeitig min 40MB an RAM allozieren.

    Ich schreibe ganz bewusst "mehr oder weniger" kurzzeitig, denn das führt mich zu einem weiteren Thema.

    Du solltest ihn wenn Du ihn oft durchlaufen lässt, etwas abändern, nämlich in:

    Quellcode

    1. #include <zlib.h>
    2. /***************************************************************
    3. * Calculates a CRC32 from a given File. The caller should assure
    4. * first that the file really existst. If it doesn't then this call
    5. * returns with an "bogus" CRC Value of zero
    6. ***************************************************************/
    7. -(uint32_t)calcCRC32FromFile:(NSString*)inFilename
    8. {
    9. NSData *data = [[NSData alloc] initWithContentsOfFile:inFilename];
    10. if (data == nil)
    11. return 0; // not beauty but okay for a demo snippet ;)
    12. // replace the first parameter by the value of the start value
    13. // in order to adjust the crc computation.
    14. // a value of 0 is the proper vor a common crc32 calculation...
    15. uint32_t crc = crc32(0, (const uint8_t*)[data bytes], [data length]);
    16. [data release];
    17. return crc;
    18. }
    Alles anzeigen

    Die Veränderung ist:

    Quellcode

    1. NSData *data = [[NSData alloc] initWithContentsOfFile:inFilename];

    statt dem

    Quellcode

    1. NSData *data = [NSData dataWithContentsOfFile:inFilename];

    und dem abschliesenden

    Quellcode

    1. [data release];


    Warum das Ganze? - Nun, damit hast Du eine bessere Kontrolle über den Zeitpunkt wann der Speicher für das (fette?) NSData wieder freigegeben wird.

    Der alte Code legt nämlich das Objekt in einem sog. "AutoreleasePool" an. Und der wird, solange Du nicht die Kontrolle über ihn hast - sprich ihn selbst angelegt hast erst beim nächsten release geleert! - Das System - die Mainloop genauer gesagt legt für Dich immer automatisch für den laufenden Thread einen AutoreleasePool (ich nenn ihn mal AP) an.

    Das ist übrigens auch der Grund, warum man das beim Starten eines eigenen Threads selbst tun muss, denn jeder Thread hat seinen eigenen AP.

    Die Änderung mit dem 'alloc & initWithContentsOfFile' oben bewirkt nun, dass das Objekt nicht im AP angelegt wird, sondern der Aufrufer selbst dafür verantwortlich ist, es freizugeben.

    Und das geschieht mit dem release am Ende der Funktion - also sollte sofot immer dann geschehen, wenn Du das Objekt nicht mehr benötigst!

    Somit erfolgt die Freigabe der Resourcen immer zum exakt kontrollierten Zeitpunkt.

    Das Problem am AP des Mainthreads, den das System für Dich angelegt hast ist nämlich, dass der nicht vorhersagbar zuschlägt.

    Nun ganz so stimmt das nicht. Es gibt die Garantie, dass er nicht innerhalb der laufenden Klassenmethode zuschlägt, denn sonst wäre das Ganze ja auf Sand gebaut ;) (Ich bezeichne den AP des Mainthreads auch gerne als den Garbage-Collector von Cocoa ;)

    Wenn Du nun die NSData Objjekte, deren Speicherbedarf sich nach der Grösse des Files richten wie in meinem alten Snippet im AP anlegst(und durchaus sehr gross werden können), dann kann sich da schon mal so einiges ansammeln - Und das verbrät unnötig Speicher, denn das Objekt wird ja ohnehin nach der Berechnung der CRC nicht mehr benötigt und sollte dann seinen Speicher auch wieder zurückgeben!

    Deswegen würde ich Dir empfehlen den Code entsprechend dem Beispiel oben, abzuändern oder ggf. umzubauen.

    Alternativ kannst Du um die Funktion auch schreiben:

    Quellcode

    1. #include <zlib.h>
    2. /***************************************************************
    3. * Calculates a CRC32 from a given File. The caller should assure
    4. * first that the file really existst. If it doesn't then this call
    5. * returns with an "bogus" CRC Value of zero
    6. ***************************************************************/
    7. -(uint32_t)calcCRC32FromFile:(NSString*)inFilename
    8. {
    9. // Create an AutoreleasePool
    10. NSAutoreleasePool *pool = [NSAutoreleasePool new];
    11. NSData *data = [NSData dataWithContentsOfFile:inFilename];
    12. if (data == nil)
    13. return 0; // not beauty but okay for a demo snippet ;)
    14. // replace the first parameter by the value of the start value
    15. // in order to adjust the crc computation ...
    16. uint32_t crc = crc32(0, (const uint8_t*)[data bytes], [data length]);
    17. [pool release]; // release the pool and all collected objects within...
    18. return crc;
    19. }
    Alles anzeigen


    ..also den Kontext unter die Kontrolle eine eigenen AP's stellen, der dann beim release freigegeben wird. Aber die Lösung lohnt sich meines Erachtens erst wenn mehrere Objekte alloziert wurden, denn lohnt sich ein Pool für nur ein Objekt?
    Da finde ich das kontrollierte release auf das Objekt viel schöner und performanter ist die Sache außerdem :)


    Übrigens kann man solche Ansammlungen auch prima mit dem Debugging Tool "Object-Alloc" finden.

    Lade mal Dein altes Programm dort und lass es mal ne kurze Weile laufen! - Wetten, dass da eine Ansammlung von NSData Objekten den meisten Speicher verbrädt - und zwar pro Objeckt ungefähr die Grösse, die auch Dein File hat, ober das Du die CRC berechnest? ;)

    Ja und die liegen alle im AP und warten darauf endlich durch ein release freigegeben zu werden...

    Pro Durchlauf wird es mehr und mehr...

    Aber zum Thema AP schaust Du am Besten mal in das hervorragende Entwicklerwiki. Tom9811 hat da ja einen sehr guten Artikel verfasst. Vielleicht kann Dir Tom auch bei Detailfragen weiterhelfen.

    Ich hoffe Dieser Exkurs hat geholfen Dir den nicht ganz trivialen Sachverhalt zu erklären.

    Happy codin' !

    - James -
  • RE: Vorsicht vor wuchernden Speicherallozierungen!

    Freilich ist sie schneller, denn der Weg mit dem Kommandozeilenskripten ist ja viel Aufwendiger. Es muss erst ein Thread erzeugt werden, dann werden die Ausgaben durch eine Pipe gejagt, etc. ...

    Mich verblüfft, dass ein einziger Aufruf schon 200 ms bringt! - Das ist ja für eine schnelle CPU eine halbe Ewigkeit.

    Das liegt daran, dass nicht einfach ein Thread, sondern eine Task erzeugt wird.

    Alle "Parallelisierungsmethoden" verursachen aber eine Verlangsamung des Programmes. Es fühlt sich lediglich schneller an, weil es flüssiger ist. Apple wies daher früher darauf hion, dass man dies nur tun soll, wenn es für den Nutzer sinnvoll ist, zu länger auf das Ergebnis zu warten, dafür aber die Software weiter bedienen zu können. Heute scheinen sie das anders zu sehen. ;)


    Die Änderung mit dem 'alloc & initWithContentsOfFile' oben bewirkt nun, dass das Objekt nicht im AP angelegt wird, sondern der Aufrufer selbst dafür verantwortlich ist, es freizugeben.

    Und das geschieht mit dem release am Ende der Funktion - also sollte sofot immer dann geschehen, wenn Du das Objekt nicht mehr benötigst!

    Somit erfolgt die Freigabe der Resourcen immer zum exakt kontrollierten Zeitpunkt.


    Das ist leider nicht richtig. Es fußt auf der stillschweigenden Annahme, dass -alloc(NSData) und -initWithFile:(NSData) selbst ekeine Objekte im ARP anlegen. Das ist aber nicht bekannt. Ganz im Gegenteil: Folgender Code ist etwa durchaus beliebt:

    Quellcode

    1. - (MyClass*)init {
    2. self = [super init];
    3. if( self )
    4. [self setContainer:[NSArray arrayWithObjects:@"Tom9811", @"James", nil]];
    5. ...

    Auch bei einem -release(NSObject), der zu einem -dealloc(MyClass) führt, wäre das Array weiter im Speicher und würde ebenfalls erst am Ende der Run - Loop vernichtet.

    Die einzig sichere Variante, keinen "Dreck" zu hinterlassen, habe ich hier beschrieben:
    macentwicklerwelt.net/index.ph…em:_Gro.DF_wachsender_ARP
    ab
    "Schließlich bietet es sich an, eigene ARP zu verwenden, die man etwa wieder leert."

    Nun ganz so stimmt das nicht. Es gibt die Garantie, dass er nicht innerhalb der laufenden Klassenmethode zuschlägt, denn sonst wäre das Ganze ja auf Sand gebaut ;) (Ich bezeichne den AP des Mainthreads auch gerne als den Garbage-Collector von Cocoa

    Die Garantie lautet, dass nicht vor Ende der Run - Loop der ARP geleert wäre. Sonst wären nämlich z.B. convenience Allocators auf Sand gebaut. Daher ist der Zeitpunkt der Aufgabe exakt defniert und kann zudem von dir durch ein eigenes ARP-Objekt bestimmt werden. Das ist definitiv etwas komplett anderes als GC.
    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"?
  • RE: Vorsicht vor wuchernden Speicherallozierungen!

    Original von Tom9811
    ...
    Die Garantie lautet, dass nicht vor Ende der Run - Loop der ARP geleert wäre. Sonst wären nämlich z.B. convenience Allocators auf Sand gebaut. Daher ist der Zeitpunkt der Aufgabe exakt defniert und kann zudem von dir durch ein eigenes ARP-Objekt bestimmt werden. Das ist definitiv etwas komplett anderes als GC.


    Hallo Tom,

    Ah Danke für Diese Ausführungen! Siehst Du, das war mir neu!

    Ich wusste schon, warum ich auf Dich - dem "Meister der Speicherallozierung und Retains" verwiesen habe! :)

    Das erklärt dann natürlich erst Recht, warum Dir, MetalSnake der Speicher ausgeht.

    So gesehen ist es dann ja noch wichtiger sich nicht nur auf den AutoreleasePool zu verlassen - freilich nicht im Sinne der Verlässlichkeit, sondern vielmehr im Sinne des "Wann gibt er all die Objekte, die in ihm landen wieder frei"...

    Nochmals vielen Dank für Deine Ausführungen!

    Schöne Grüsse

    - Peter -
  • RE: Vorsicht vor wuchernden Speicherallozierungen!

    Man kann sich schon auf den ARP verlassen. Das ist ja der Unterschied zur GC. Man kann bloß nicht immer das Verhalten des automatisch installierten ARP gebrauchen.

    Er sollte sich einen eigenen ARP anlegen. Das ist immer noch die sicherste Methode, um derlei ARP-Müll zu vermeinden. Aber Vorsicht, da gibt es eine Falle! Sämtliche Objekte, die man im ARP angelegt hat, sind dann ja auch weg. Diese muss man vorher retainen, wobei sich Container anbieten, in den man die "zu sichernden Objekte" hereinhängt.

    BTW: Im C++-Artikel erkläre ich das eigentlich prägnanter. Ich sollte das noch einmal übernehmen.
    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"?
  • RE: Vorsicht vor wuchernden Speicherallozierungen!

    Erstmal danke James und Tom für die ausführlichen Erklärungen :)

    Original von James
    Mich verblüfft, dass ein einziger Aufruf schon 200 ms bringt! - Das ist ja für eine schnelle CPU eine halbe Ewigkeit.

    Schnell ist ein ziemlich relativer Begiff ;) Ich hab einen g4 733MHz, heutzutage gilt das wohl eher nicht mehr als schnell…


    Wenn Du nun diese CRC32 Berechnung sehr oft im Programm durchführst, dann lohnt sich ein Libcall über den crc32 der zlib sehr, sehr schnell.

    Ja, habe gerade dein überarbeitetes snipped benutzt das klappt wunderbar mit 2500 aufrufen, nur das mit der NSTask nippelt immer bei dem 250. Aufruf mit dem Fehler ab:

    Quellcode

    1. 2005-07-20 14:16:37.826 SnakeRom[12406] An uncaught exception was raised
    2. 2005-07-20 14:16:37.827 SnakeRom[12406] *** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value
    3. 2005-07-20 14:16:37.827 SnakeRom[12406] *** Uncaught exception: <NSInvalidArgumentException> *** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value

    also hab ich die jeweils nur 200 mal durchlaufen lassen und schon 11 Sekunden gespart :)

    Also schmeiß ich jetzt den NSTask kram raus, werd mir dann gleich auch mal angucken wie ich mit der zlib die Dateien gunzippe und wieder gzippe. und mich auch mal näher mit den CHUD Tools beschäftigen.
  • RE: Vorsicht vor wuchernden Speicherallozierungen!

    Die Fehlermeldung rührt mutmaßlich daher, dass er das geforderte Pbjekt nicht mehr herstellen kann und dir ein nil zurückgab. Dies hast du dann versucht einzufügen, was nicht geht.

    Hin und wieder sollte man doch auf nil prüfen. ;)
    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"?
  • Wieso kann er das Object dann die 249 mal vorher herstellen und dann plötzlich nicht mehr?

    Vorne weg: Ich möchte für eine Datei die als .gz komprimiert ist den CRC32 Wert berechnen, dazu sollen aber die unkomprimierten Daten benutzt werden.

    Bei dem Versuch das gunzip aus der zlib zu benutzen bin ich gescheitert, die Dokumentation in dem Header ist nicht sehr verständlich wie ich finde, jedenfalls glaube ich jetzt das gzopen() dass macht was ich möchte.
    Habe da zum Testen mal dies geschrieben:

    Quellcode

    1. -(void)gunzipUsingZlib:(NSString *)inFileName
    2. {
    3. NSData *data = [[NSData alloc] init];
    4. data = gzopen(inFileName, "r");
    5. unsigned long crc = crc32(0, (const uint8_t*)[data bytes], [data length]);
    6. NSLog(@"%u", crc);
    7. }


    Da meckert der Compiler aber: "warning: passing argument 1 of 'gzopen' from incompatible pointer type"

    Habe dann mal testweise inFileName in "/blah/blup.gz" geändert, dann ist zwar der Compiler zufrieden, aber in data steht nichts.
    gzopen() gibt einen file pointer.
  • Original von MetalSnake
    Bei dem Versuch das gunzip aus der zlib zu benutzen bin ich gescheitert, die Dokumentation in dem Header ist nicht sehr verständlich wie ich finde, jedenfalls glaube ich jetzt das gzopen() dass macht was ich möchte.
    Habe da zum Testen mal dies geschrieben:

    Quellcode

    1. -(void)gunzipUsingZlib:(NSString *)inFileName
    2. {
    3. NSData *data = [[NSData alloc] init];
    4. data = gzopen(inFileName, "r");
    5. unsigned long crc = crc32(0, (const uint8_t*)[data bytes], [data length]);
    6. NSLog(@"%u", crc);
    7. }


    Da meckert der Compiler aber: "warning: passing argument 1 of 'gzopen' from incompatible pointer type"

    Habe dann mal testweise inFileName in "/blah/blup.gz" geändert, dann ist zwar der Compiler zufrieden, aber in data steht nichts.
    gzopen() gibt einen file pointer.

    Ich nehme an, da es sich bei der zlib um eine C-Bibliothek handelt, erwartet die gzopen() funktion einen character Zeiger und kann mit dem NSString nichts anfangen.
    Du muesstest vorher den NSString in einen C-String umwandeln:

    Quellcode

    1. char cstr[[inFileName length]+1];
    2. BOOL success = [inFileName getCString:cstr maxLength:([inFileName length]+1) encoding:NSASCIIStringEncoding];
    3. if(success)
    4. {
    5. ...
    6. }

    Und soweit ich das jetzt in der zlib Header-Datei gesehen habe, bekommst Du von gzopen() einen "gzFile" als pointer zurueck oder NULL wenn was schief ging. Zum einen kannst Du den nicht einem NSData zuweisen, zum anderen ist an der Stelle "nur" die Datei erstmal geoeffnet, die Daten lesen musst Du dann trotzdem noch mit gzread().

    Quellcode

    1. gzFile myGzFile = gzopen(str,"r");
    2. if(myGzFile != NULL)
    3. {
    4. NSMutableData *myGzData = [[NSMutableData alloc] init];
    5. char readbuffer[8192]; // some value divideable by 4
    6. int readlen = 0;
    7. while((readlen = gzread(myGzFile,(void *)&readbuffer[0],8192)) > 0)
    8. {
    9. // for readlen = 0 we are finished
    10. [myGzData appendBytes:(void *)readbuffer,readlen];
    11. }
    12. // we are finished with reading from gzfile
    13. // now, we can close it and make somthing with the read data...
    14. // and do not forget to release the NSData object!!!
    15. ...
    16. }
    Alles anzeigen

    Code ist nicht getestet, aber koennte so funktionieren.

    Manfred
  • Wieso kann er das Object dann die 249 mal vorher herstellen und dann plötzlich nicht mehr?

    Nun, ohne deine Debugger-Konsole lässt sich das schwer beurteilen. Aber mutmaßlich hat James Recht: Auch virtueller Speicher neigt sich mal dem Ende zu.

    Du kannst das testen, indem du vorher einmal ein anderes GROSSES! Objekt anlegst. Schafft er dann auch noch 249?
    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"?
  • @asrael: Danke das funktionierte nach ein paar kleinen Änderungen, danke :)

    Ich trau mich schon gar nicht mehr weiter zu schreiben aber es gibt noch 2 Probleme:
    Wenn in einem Pfad ein ´ vorkommt kann das ganze nicht in ein CString gewandelt werden. Wenn ich das encoding auf NSUnicodeStringEncoding stelle klappt die Umwandlung gar nicht mehr.

    Und die 250 hat wieder zugeschlagen, nach dem 250. mal gibt mir [fm copyPath:fromPath toPath:toPath handler:nil] NO zurück.
    Die Datei wird noch erstellt aber mit 0byte. Platte ist noch genügend Frei, und es ist auch egal ob die 250 Dateien im Schnitt 4mb oder 15mb sind. Es ist auch nicht abhängig von der Datei sondern immer nur die Anzahl.
    Also ich steh grad echt aufm Schlauch glaub ich…
  • Original von MetalSnake
    Ich trau mich schon gar nicht mehr weiter zu schreiben aber es gibt noch 2 Probleme:
    Wenn in einem Pfad ein ´ vorkommt kann das ganze nicht in ein CString gewandelt werden. Wenn ich das encoding auf NSUnicodeStringEncoding stelle klappt die Umwandlung gar nicht mehr.


    Hallo MetalSnake,

    Probier mal statt -[NSString cString] ein -[NSString UTF8String]; ;)

    Und die 250 hat wieder zugeschlagen, nach dem 250. mal gibt mir [fm copyPath:fromPath toPath:toPath handler:nil] NO zurück.
    Die Datei wird noch erstellt aber mit 0byte. Platte ist noch genügend Frei, und es ist auch egal ob die 250 Dateien im Schnitt 4mb oder 15mb sind. Es ist auch nicht abhängig von der Datei sondern immer nur die Anzahl.
    Also ich steh grad echt aufm Schlauch glaub ich…


    Hast Du das Programm schon mal unter ObjectAlloc laufen lassen?
  • Original von James
    Original von MetalSnake
    Ich trau mich schon gar nicht mehr weiter zu schreiben aber es gibt noch 2 Probleme:
    Wenn in einem Pfad ein ´ vorkommt kann das ganze nicht in ein CString gewandelt werden. Wenn ich das encoding auf NSUnicodeStringEncoding stelle klappt die Umwandlung gar nicht mehr.


    Hallo MetalSnake,

    Probier mal statt -[NSString cString] ein -[NSString UTF8String]; ;)


    Du meinst statt [inFileName getCString:cstr … [inFileName getUTF8String:cstr …? Das scheint es jedenfalls nicht zu geben.



    Hast Du das Programm schon mal unter ObjectAlloc laufen lassen?


    Gibts dazu eine Anleitung? Habe bei Apple jetzt nur dies gefunden developer.apple.com/documentat…/20001882-97995-TPXREF162 da steht aber nicht wirklich beschrieben wofür alles steht.

    Ich hab da jedenfalls sehr viele rote, gelbe und blaue Balken und ziemlich viele sind sehr lang. *g*
  • Original von MetalSnake
    Original von James
    Original von MetalSnake
    Ich trau mich schon gar nicht mehr weiter zu schreiben aber es gibt noch 2 Probleme:
    Wenn in einem Pfad ein ´ vorkommt kann das ganze nicht in ein CString gewandelt werden. Wenn ich das encoding auf NSUnicodeStringEncoding stelle klappt die Umwandlung gar nicht mehr.


    Hallo MetalSnake,

    Probier mal statt -[NSString cString] ein -[NSString UTF8String]; ;)


    Du meinst statt [inFileName getCString:cstr … [inFileName getUTF8String:cstr …? Das scheint es jedenfalls nicht zu geben.


    Ahoi Snake,

    Nö, ich meine schon -[NSString UTF8String] ;)

    Es geht doch darum die C-String Repräsentation eines NSString Objektes abzufragen?






    Hast Du das Programm schon mal unter ObjectAlloc laufen lassen?


    Gibts dazu eine Anleitung? Habe bei Apple jetzt nur dies gefunden developer.apple.com/documentat…/20001882-97995-TPXREF162 da steht aber nicht wirklich beschrieben wofür alles steht.

    Ich hab da jedenfalls sehr viele rote, gelbe und blaue Balken und ziemlich viele sind sehr lang. *g*

    Ruf mal innerhalb ObjectAlloc den "About-Requester" auf - da steht drin, was die einzelnen Farben zu bedeuten haben.

    Generell gilt - der Balken ist nur eine graphische Repräsentation des Zahlenwertes daneben und der steht - solange nicht "Count are Bytes" angewählt ist, die Summe der Instanzen und Retains des jeweiligen Objektes. Wenn Du da eines stehen hast, das wider Erwartens nicht mehr herunterzählt, dann solltest Du mal nachsehen, ob ein release fehlt. Es sei denn das Objekt wird von einem ARP geführt. Dann erfolgt die Freigabe der zugehörigen Objekte erst beim nächsten release dieses ARP's

    Dei Mark-Funktion ist auch ganz nütlich. Die kann man gut gebrauchen, wenn mal man den Zuwachs - also das Delta sehen will - z.B. wie der Objektallozierungstatus ist, wenn sich ein Programm mal "beruhigt" - sich also grundinitialisiert hat. Marke setzen und danach mal was machen - Buttons klicken etc.


    Spiele einfach mit herum. ich finde dass ObjectAlloc ein sehr wichtiges und auch nützliches Werkzeug ist, um Memoryleaks auf die Schliche zu kommen.

    Auch kann man dort gleich sehen, ob es manchmal nicht besser ist selbst einen ARP anzulegen und die Verwaltung der Instanzen nicht dem default ARP aufzubürden. ;)