DEUTSCHE VERSION |
|
Links | | | Forums | | | Comments | | | Report news |
Chat | | | Polls | | | Newsticker | | | Archive |
amiga-news.de Forum > Programmierung > Progamm<->Internet<->Programm | [ - Search - New posts - Register - Login - ] |
1 2 3 -4- | [ - Post reply - ] |
2006-08-22, 15:47 h Ralf27 Posts: 2779 User |
Zitat: Hab es eben getestet und etwas interesantes festgestellt: 1. Die Daten werden wirklich hintereinander im Speicher abgelegt. Wenn z.b. size&=10 ist, dann ist buffer2&=buffer&+size&, um es mal so zu tippen. Laut Handbuch belegen die Strings einen Tabelle und von da aus geht dann wohl ein "Link" zu einem anderen Speicherbereich. Das obrige Beispiel hab ich aber testweise anderst geschrieben: code:buffer1&=0 buffer2&=0 buffer1&=SADD(SPACE$(10)) buffer2&=SADD(SPACE$(10)) PRINT buffer1&,buffer2& Nicht das er dann noch die Variable buffer2& zwischen denn Strings anlegt, da ich auch wissen wollte wie die Strings im Speicher liegen. -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-22, 15:51 h whose Posts: 2156 User |
@Ralf27: Dann müßte auch irgendwo im Handbuch stehen, was MB mit temporären Variablen veranstaltet. Such da mal ein wenig. Sollten temporäre Stringvariablen tatsächlich auch bei MB auf dem Heap landen, bekommst Du mit ziemlicher Sicherheit irgendwann ein Problem mit dem Konstrukt. Bei GFA stand es im Handbuch, daß temporäre Stringvariablen im Variablenbereich landen und ein "unsichtbares" Label bekommen. Da bestand keine Gefahr, daß solche Strings aus Versehen überschrieben werden. Dafür wurde das Speicherproblem der Garbage Collection überlassen, auch nicht unbedingt optimal... Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Answer - Quote - Direct link - ] |
2006-08-22, 16:02 h Ralf27 Posts: 2779 User |
Hm, stimmt schon. Hab hier auch im Handbuch was von"Garbage Collection" gefunden. Ich sollte wohl wirklich in Zukunft solche Konstrukte lieber vermeiden. -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-22, 16:10 h whose Posts: 2156 User |
Zitat: Ja, das ist normal. In BASIC werden Variablen halt in einer "Label-Tabelle" festgehalten (da ist auch der Speicherbedarf festgehalten), der eigentlich belegte Speicher einer Variablen befindet sich meist in einem gesonderten Bereich, dem Variablen-Bereich. Das ist u.A. der Grund dafür, weshalb die wenigsten Interpreter Strings von unbegrenzter Länge akzeptieren. Daß bei Deinem Test die beiden Adressen schön geordnet hintereinander liegen, sagt aber noch nicht viel. Es ist halt die Frage, wo genau der Speicher dafür angefordert wurde und für welchen Abschnitt Deines Programms dieser Speicher "gültig" bleibt. Ist es der Variablenbereich, weiß der Interpreter/Compiler immer, wie lang der angelegte String ist, auch wenn der "Gültigkeitsbereich verlassen wird" (ich meine hier den Gültigkeitsbereich lokaler Variablen, temporäre Variablen, die in der Label-Tabelle erfaßt und im Variablenspeicher abgelegt sind, gelten für das ganze Programm oder global). Werden die beiden Strings auf den Heap geschmissen, weiß er das spätestens am Ende des Gültigkeitsbereichs nicht mehr und einer oder beide Strings werden irgendwann durch andere Werte überschrieben. Da MB auch CONST unterstützt, gehe ich aber davon aus, daß es auch lokale Variablen unterstützt, die einen beschränkten Gültigkeitsbereich haben. Das dürfte dann auch auf die temporären Strings zutreffen. Genau das ist dann das gefährliche. Solltest Du den "Gültigkeitsbereich" dieser Strings verlassen und z.B. weitere temporäre Variablen anlegen, ist der Inhalt der beiden Strings für Dein Programm tabu bzw. Du kannst nicht sagen, was sich bei einem erneuten Zugriff darin befindet. Richtig haarig wirds dann, wenn Funktionen "von außen" darauf zugreifen müssen. Du mußt diesen Funktionen mit Deinem Programm garantieren, daß sich gültige Werte in diesem Speicherbereich befinden. Bei temporären Variablen mit eingeschränktem Gültigkeitsbereich kannst Du es aber nicht, wenn der Gültigkeitsbereich vor dem Aufruf der "Funktion von außen" verlassen wurde. Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ Dieser Beitrag wurde von whose am 22.08.2006 um 16:33 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-08-22, 16:20 h whose Posts: 2156 User |
Zitat: Naja, die "Garbage Collection" gehört eigentlich zu jedem BASIC-Dialekt. Das Teil räumt einfach nur den Variablenspeicher auf, wenn selbiger knapp wird. Da wird bei Interpretern z.B. der ganze Kram nur neu geordnet (defragmentiert, sozusagen), um am Ende des Variablenbereichs wieder Platz für z.B. einen längeren String zu bekommen. Bei GFA war das Problem, daß auch temporäre Variablen im Variablenspeicher statt auf dem Heap landen (lokale Variablen hingegen nicht), so daß die temporären Variablen Speicher "geklaut" haben, den man nicht ausdrücklich freigeben konnte. Da kam die Garbage-Collection bei Programmen mit vielen temporären Variablen halt sehr oft zum Einsatz, was sich sehr negativ auf die Geschwindigkeit auswirkte. Beim Compiler war das kein Thema mehr, da dieser ja "voraussehen" kann, was mit verschiedenen Variablen gemacht wird und bei Bedarf einfach wieder Speicher vom System anfordern kann. Das Konstrukt, was Du da verwendest, ist im Prinzip eigentlich schon nützlich, aber Du mußt darauf achten, wo Du es anwendest und wie es sich im weiteren Verlauf des Programms verhält (siehe das vorherige Posting). Da solltest Du also nochmal im Handbuch nachschlagen. Bei AmigaBASIC z.B. geht das irgendwann schief, auch wenn es da ab und an verwendet wurde (wenn auch eher selten in diesem Zusammenhang). Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Answer - Quote - Direct link - ] |
2006-08-22, 16:48 h Holger Posts: 8116 User |
Zitat: Wie gesagt, das heisst nicht, dass die Konstruktion sicher ist. Wenn Du schon etwas zu gc in Deinem Handbuch gefunden hast, werden höchstwahrscheinlich alle String-Operationen per default in einem neuen Heap-Bereich durchgeführt, um dann zu einem späteren Zeitpunkt durch den gc freigegeben zu werden. Das ist bei einer Abfolge von mehreren String-Manipulationen durchaus effizienter, als ein ständiges Belegen und Freigeben. Für diese eigentlich temporären Strings ist es dann aber definitiv eine Zeitbombe, sie als Puffer zu benutzen, weil Du keine Kontrolle darüber hast, wann der gc sie freigeben wird. Und wenn es so ist, wie Du sagst, dass zugewiesene Strings garantiert feste Adressen haben, ist diese Basic-Implementierung anfällig für Speicherfragmentierung. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-22, 17:07 h whose Posts: 2156 User |
@Holger: Da kommt man schon drauf, wenn man liest, daß der MB-Compiler eine Garbage-Collection einsetzt. Allerdings kann man das wahlweise aktivieren, wie Ralf schon andeutete. Die Anfälligkeit für Fragmentierung ist dann wohl eher eine Frage der Wahl der Compiler-Optionen. Nichts desto trotz sollte Ralf mal nachsehen, wie MB mit temporären Variablen genau umgeht, das muß doch irgendwo im Handbuch stehen... Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Answer - Quote - Direct link - ] |
2006-08-22, 17:17 h Ralf27 Posts: 2779 User |
Ok, ich hab denn Code eben etwas umgebaut, läuft aber leider dennoch nicht. Ich komme bis "kopieren...", das wars. Es wird leider nix kopiert.code:--DEFINT a-z size&=100 in_port&=CreateMsgPort&:IF in_port&=0 THEN Ende out_port&=CreateMsgPort&:IF out_port&=0 THEN Ende in_file&=xOpen&(SADD("ram:test"+CHR$(0)),MODE_OLDFILE&) IF in_file&=0 THEN Ende out_file&=xOpen&(SADD("ram:test7"+CHR$(0)),MODE_NEWFILE&) IF out_file&=0 THEN Ende buffer1&=AllocMem&(size&,MEMF_PUBLIC&):IF buffer1&=0 THEN Ende buffer2&=AllocMem&(size&,MEMF_PUBLIC&):IF buffer2&=0 THEN Ende buffer&=buffer1& PRINT"Kopiere..." bytes_read=xRead(in_file&,buffer&,size&) WHILE bytes_read>0 StartWrite out_file&,buffer&,bytes_read,out_port& IF buffer&=buffer1& THEN buffer&=buffer2& ELSE buffer&=buffer1& END IF StartRead in_file&,buffer&,size&,in_port& WaitDosIO out_port&,dummy WaitDosIO in_port&,bytes_read WEND PRINT"fertig!" Ende: IF buffer2& THEN FreeMem! buffer2&,size& IF buffer1& THEN FreeMem! buffer1&,size& IF out_file& THEN x=xClose(out_file&) IF in_file& THEN x=xClose(in_file&) IF out_port& THEN DeleteMsgPort out_port& IF in_port& THEN DeleteMsgPort in_port& SUB StartRead(bptr&,buffer&,size&,port&) fh&=bptr&<<2 IF fh&<>0 AND PEEKL(fh&+fh_Type%)<>0 THEN packet&=AllocDosObject&(DOS_STDPKT&,TAG_END&) IF packet& THEN POKEL packet&+dp_Port%,port& POKEL packet&+dp_Type%,ACTION_READ& POKEL packet&+dp_Arg1%,PEEKL(fh&+fh_args%) POKEL packet&+dp_Arg2%,buffer& POKEL packet&+dp_Arg3%,size& PutMsg PEEKL(fh&+fh_Type%),PEEKL(packet&+dp_Link%) END IF END IF END SUB SUB StartWrite(bptr&,buffer&,size&,port&) fh&=bptr&<<2 IF fh&<>0 AND PEEKL(fh&+fh_Type%)<>0 THEN packet&=AllocDosObject&(DOS_STDPKT&,TAG_END&) IF packet& THEN POKEL packet&+dp_Port%,port& POKEL packet&+dp_Type%,ACTION_WRITE& POKEL packet&+dp_Arg1%,PEEKL(fh&+fh_args%) POKEL packet&+dp_Arg2%,buffer& POKEL packet&+dp_Arg3%,size& PutMsg PEEKL(fh&+fh_Type%),PEEKL(packet&+dp_Link%) END IF END IF END SUB SUB WaitDosIO(port&,rc) x=WaitPort(port&) msg&=GetMsg&(port&) packet&=PEEKL(PEEKL(msg&+mn_Node%)+ln_Name%) rc=PEEKL(packet&+dp_Res1%) FreeDosObject DOS_STDPKT&,packet& END SUB http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-22, 17:25 h Ralf27 Posts: 2779 User |
Zitat:Hm, nichts gefunden. In der Hinsicht ist das MB-Handbuch wesentlich spartanischer als das AmigaBasic-Handbuch, das wenigstens noch Beispiele drin hat, bzw. viel mehr erklärt wird. Im MB-Handbuch geht es vorallem um die Befehle, denn Editor und denn Compiler. -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-22, 17:45 h Holger Posts: 8116 User |
Zitat:Dann liegt Dein Fehler irgendwo zwischen "kopieren..." und "fertig!". Im Ernst, hast Du schonmal ein paar PRINTs mehr eingefügt, um den Fehler zu lokalisieren? Zitat:Geht das so wirklich, CreateMsgPort& ohne runde Klammern? Ich würde trotzdem CreateMsgPort&() schreiben, aus naheliegenden Gründen.code:in_port&=CreateMsgPort&:IF in_port&=0 THEN Ende out_port&=CreateMsgPort&:IF out_port&=0 THEN Ende Übrigens kann es helfen, wenn Du SnoopDOS vorher startest und den Packet-Debugger aktivierst. Dann siehst Du evtl., was Dein Programm an das FileSystem sendet (falls es nicht schon vorher abstürzt). mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-22, 18:29 h Holger Posts: 8116 User |
Zitat:Haut so nicht hin, da mn_Node eine in der Message eingebettete Struktur ist. Korrekt müsste der Zugriff packet&=PEEKL(msg&+mn_Node%+ln_Name%) lauten, vorausgesetzt, dass mn_Node% erwartungsgemäß 0 ist, da die Struktur am Anfang der Message liegt. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-22, 21:15 h Ralf27 Posts: 2779 User |
Zitat: Das isses! Jetzt läuft es! Danke! Respekt! -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-22, 21:18 h Ralf27 Posts: 2779 User |
Zitat: Das läuft so. Aber es stimmt schon, damit man es als Funktion erkennt. MBasic würde sogar jammern wenn ich CreateMsgPort als Variable nutzen würde(wenn ich vorher auch die Includes eingebunden habe, logisch). Im ersten Beispiel hatte ich es ja auch mit () stehn. Sieht auch besser aus. -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-23, 14:20 h Ralf27 Posts: 2779 User |
Eine Sache ist da noch: Wenn ich das Lesen starten und dann sozusagen "abbreche", dann seh ich wieviele Bytes ich bekommen habe. Aber ganz anderst sieht es beim schreiben aus, das da wohl nicht kontrolliert wird. Und das verwundert mich etwas. Kann es denn nicht sein das bis zu diesem Zeitpunkt nur ein Teil gespeichert wurde und der Rest noch nicht sicher ist? -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-23, 15:09 h Holger Posts: 8116 User |
Zitat: Was meinst Du mit "abbrechen"? Du musst immer auf die Antwort warten, d.h. Du bekommst auch immer die Anzahl gelesener/geschriebener bytes zurückgeliefert. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-23, 15:15 h Ralf27 Posts: 2779 User |
@Holger: Hm, dann bringt mir das ganze ja doch nichts. Ich kann doch dann eigentlich auch genausogut mit Read() so lange warten bis ich vermutlich Daten im Buffer habe. Und dieses "vermutlich" läst mich halt auch wieder Haare raufen. Was ich bräuchte wäre nur ne Möglichkeit um zu sehn ob was da ist und wieviel, damit beim Aufruf von Read() der Befehl gleich wieder zurück kommt und nicht alles blockiert. Da ist das da oben eigentlich quasi(fast) genau so. -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-23, 15:39 h Holger Posts: 8116 User |
Zitat: Mir ist nicht ganz klar, wie die Struktur Deines Programm aussehen soll. Die asynchrone I/O bietet Dir die Möglichkeit, beliebige Dinge während der Read-Operation durchzuführen, damit ist eigentlich kaum noch eine Einschränkung vorstellbar für, was auch immer Du tun willst. Wenn Du wissen willst, ob Daten anliegen, kannst Du einfach überprüfen, ob am zugehörigen MessagePort eine Antwort vorliegt. Wenn nicht, sind noch keine Daten vorhanden. Natürlich musst Du irgendwann, spätestens bevor das Programm sich beendet, definitiv auf die Beantwortung des Packets warten, um dessen Speicher freizugeben und die Datei zu schließen. Aber das ist im Allgemeinen unproblematisch, da alle Netzwerkverbindungen auch einen Timeout haben. Zur Sicherheit gibst Du eine Meldung aus, dass Du auf die Beendigung der Netzwerkverbindngen wartest, damit der Benutzer nicht denkt, dass Dein Programm hängt. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-23, 15:58 h Ralf27 Posts: 2779 User |
Zitat:Ich brauch nicht immer Daten, sondern nur dann wenn sie da sind. Das ganze was ich vor habe ist nicht Zeitkritisch, aber vermutlich werd ich auch da sowas wie ein TimeOut einbauen. Das Problem war halt immer, das Read einfach immer solange wartet bis die anzahl Bytes da waren, bis zum TimeOut (falls eins kommt, bzw. wie lange dauert das eigentlich?) Das möchte ich halt umgehn und deswegen wüße ich zugerne wieviele Daten ich anfordern darf, ohne das Read() eine Siesta hinlegt. Zitat: Hm, leider hab ich kein Plan wie ich aus dem Port die Info über die Anzahl der vorhanden Bytes raus bekomme. EDIT: Äh, so wie bei WaitDOSIO die Anzahl der gelesen Bytes? code:msg&=GetMsg&(in_port&) packet&=PEEKL(msg&+mn_Node%+ln_Name%) Bytesdiedasind=PEEKL(packet&+dp_Res1%) Kann es so einfach sein?!? -- http://www.alternativercomputerclub.de.vu [ Dieser Beitrag wurde von Ralf27 am 23.08.2006 um 16:04 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-08-23, 17:33 h Holger Posts: 8116 User |
Zitat:Wenn keine Message vorhanden ist, ist die Anzahl 0. Wenn eine Message vorhanden ist, ist die Anzahl mindestens so groß, wie die Anzahl der gelesenen bytes. Und wie Du die herausbekommst, weißt Du ja. Zitat:Ja. Zitat:Also bislang war die Rede vom Download einer Datei. Wenn Du die nicht brauchst, dann fordere sie auch nicht an. Für die Implementierung eines Netzwerkprotokolls sind Dateioperationen nicht geeignet. Dafür gibt es ja Netzwerk-APIs. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-23, 17:46 h Ralf27 Posts: 2779 User |
@Holger: Ursprünglich wollte ich in diesem Thread wissen ob es für normal sterbliche eine einfach Möglichkeit gibt ein Programm über das Netzwerk zu einem anderen Programm zu verbinden. Dann bin ich auf ein Programm vom Thomas gestoßen das mit diesem TCP: sogar eine Datei runterläd. Bzw. wollte ich dann auch eine Updatefunktion einbauen. Es geht hier im ganzen Thread dann um zwei Dinge: 1. Netzwerkverbindung zwischen zwei Programmen für ein Spiel, das nicht Zeitkritisch ist. 2. eine Programmupdatefunktion Nr.2 läuft erfolgreich Nr.1 macht noch Probleme, bzw. wohl bald nicht mehr. Edit: Zitat:Das ist mir auch klar, aber ich hab schon recht lange gebraucht das hier zu verstehn, ich will euch das mit dem Netzwerk-API nicht antun. -- http://www.alternativercomputerclub.de.vu [ Dieser Beitrag wurde von Ralf27 am 23.08.2006 um 17:50 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-08-23, 18:01 h Holger Posts: 8116 User |
@Ralf27: So viel komplizierter ist das dann auch nicht mehr. Aber wie auch immer, reichen Dir die Informationen jetzt für Dein Vorhaben? mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-08-23, 21:27 h Ralf27 Posts: 2779 User |
@Holger: Also, wenn es so läuft wie es laufen sollte, dann müßte ich mit diesen Infos die Netzwerkstory im Programm einbauen können. Ich will auch endlich wieder eine neue Version von diesem Programm online stellen, aber leider hängt es seit Wochen an der Grafik. Ich selbst bin leider ein noch schlechterer Pixler als Programmierer und ich will keinem meinem Pixelwunder zumuten. Da muß ich noch was machen. -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-24, 22:47 h Ralf27 Posts: 2779 User |
Ein Problem hat sich da eben eröffnet: Ich hab schon eine schleife mit einem port&, mit dem ich das Menu, das Fenster und die Maus bearbeite. Wenn ich da keinen Input habe, dann geht der Task& mit WaitPort(port) schlafen. Aber wenn der pennt, dann kann ich ja auch nich wissen ob neue Daten vom Netzwerk, bzw. vom anderen Port reinkommen. Wie kann ich das ändern? -- http://www.alternativercomputerclub.de.vu [ - Answer - Quote - Direct link - ] |
2006-08-25, 01:15 h NoImag Posts: 1050 User |
Zitat: Du darfst nicht WaitPort() verwenden, sondern Du musst Wait() verwenden. Bei Wait() wartest du nicht auf einen bestimmten Port, sondern auf verschiedene Signals. Zu jedem Port gehört ein Signal (findest du in der MessagePort-Struktur). Die Signals aller Deiner Ports musst du bei Wait() angeben. Tschüß [ - Answer - Quote - Direct link - ] |
2006-08-25, 01:42 h Holger Posts: 8116 User |
@Ralf27: Du musst halt auf mehrere Port gleichzeitig warten. Das ist ja der Vorteil der asynchronen I/O, dass man genau das tun kann. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
1 2 3 -4- | [ - Post reply - ] |
amiga-news.de Forum > Programmierung > Progamm<->Internet<->Programm | [ - Search - New posts - Register - Login - ] |
Masthead |
Privacy policy |
Netiquette |
Advertising |
Contact
Copyright © 1998-2024 by amiga-news.de - all rights reserved. |