 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
kawe
Anmeldungsdatum: 25.03.2012 Beiträge: 41
|
Verfasst am: 16.11.2012, 01:23 Titel: Wie groß dürfen denn Strings nun wirklich sein? |
|
|
Mal eine ganz "einfache" Frage.
Warum stürzt denn folgendes Programm bei mir in fb 0.24 (Windows) ab?
Ich dachte, Strings dürfen bis zu 2GB groß sein?
Code: | Dim As String * 10000000 text
Print "Hierhin kommt das Programm gar nicht mehr ..."
sleep |
|
|
Nach oben |
|
 |
ALWIM

Anmeldungsdatum: 08.08.2006 Beiträge: 1048 Wohnort: Niederbayern
|
Verfasst am: 16.11.2012, 02:04 Titel: |
|
|
Code: | Dim SHARED AS String text(0 TO 10000000)
Print "Hierhin kommt das Programm gar nicht mehr ..."
SLEEP |
Probiere es mal so!
Das behebt das Problem!!!
Edit:
Code: | Dim SHARED AS String * 10000000 text |
So geht es auch! Es fehlt nur das Shared!!!
Gruß
ALWIM _________________ SHELL SHUTDOWN -s -t 05 |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 16.11.2012, 02:32 Titel: |
|
|
Das SHARED "fehlt" nicht, sondern tut nur etwas ganz anderes. Der String wird in deinem ursprünglichen Beispiel meiner Vermutung nach (da er ein String fester Länge ist), auf dem Stack allokiert, welcher typischerweise nur ein paar MB groß ist. SHARED-Variablen werden immer auf dem Heap allokiert, weswegen ALWIMs zweiter Vorschlag zufälligerweise funktioniert. Der erste Vorschlag ist natürlich vollkommen sinnfrei, da er ein Array von Strings auf dem Heap allokiert. FB macht es so meiner Meinung nach nicht immer einfach zu sehen, was auf dem Stack landet und was auf dem Heap, was die ganze Sache sehr intransparent macht, vor allem da Strings keine echten Objekte sind... Da ich schon lange nix mehr mit FB gemacht habe, weiß ich jetzt auch nicht aus dem stehgreif, was ein sauberer Ansatz wäre, eine String-Variable fester Länge auf dem Heap zu erzeugen, vermutlich mit NEW. SHARED ist jedenfalls nicht sauber, da es den globalen Namespace verschmutzt.
Randbemerkung: In C++ wäre also das ursprüngliche Beispiel mit der Deklaration Code: | char text[10000000]; | vergleichbar, die Lösung wäre in etwa Code: | char *text = new char[10000000]; |
_________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
Sebastian Administrator

Anmeldungsdatum: 10.09.2004 Beiträge: 5969 Wohnort: Deutschland
|
Verfasst am: 16.11.2012, 12:20 Titel: |
|
|
Hallo,
Jojo trifft mit seinem Posting den Nagel auf den Kopf.
Wenn man größere Speicherbereiche am Stück reservieren möchte, eignet sich dazu am besten CALLOCATE.
Im Folgenden ein kleines Beispiel, das erklärt, wie's funktioniert:
Code: | Dim As ZString Ptr text ' Zeiger, der bisher auf noch nichts zeigt
text = CAllocate(10000000) ' Jetzt ca. 10 MB Speicher am Stueck reservieren
' und den Zeiger darauf in "text" speichern
Print "Hierhin kommt das Programm problemlos."
Print "Der soeben reservierte Speicherplatz beginnt an Position " & text & "."
Print "Bisher enthaelt der String das hier: " & chr(34) & *text & chr(34) & " --> also nichts."
Print "Jetzt wird er mit Inhalt befuellt."
*text = "Hallo Welt, das hier ist ein Test mit einem dynamisch erzeugten Stringpuffer."
Print "Und hier die Ausgabe:"
Print chr(34) & *text & chr(34)
' Manuell angeforderten Speicherplatz wieder freigeben (wichtig!)
DeAllocate (text)
Print "Fertig. Beliebige Taste zum Beenden druecken."
sleep |
Der wesentliche Unterschied im Zugriff auf die so erzeugte Variable ist, dass man ein Sternchen voranstellen muss, wenn man den Inhalt meint. Geht kein Sternchen voraus, ist die Adresse des Speicherblocks gemeint. Vergleiche dazu das Beispielprogramm weiter oben im Posting.
In FB landet "normales" DIM auf dem Stack und REDIM auf dem Heap.
Mit SHARED zu arbeiten, wie ALWIM es vorschlägt, halte ich - genau wie Jojo - für keine so gute Idee. SHARED sollte man nur für Variablen benutzen, die auch wirklich im gesamten Programm und allen Unterprogrammen erreichbar sein müssen.
Viele Grüße!
Sebastian _________________
Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen! |
|
Nach oben |
|
 |
kawe
Anmeldungsdatum: 25.03.2012 Beiträge: 41
|
Verfasst am: 16.11.2012, 13:20 Titel: |
|
|
Zitat: | Jojo trifft mit seinem Posting den Nagel auf den Kopf.
Wenn man größere Speicherbereiche am Stück reservieren möchte, eignet sich dazu am besten CALLOCATE.
Im Folgenden ein kleines Beispiel, das erklärt, wie's funktioniert: [...] |
Ja, auch ich kann voll und ganz zustimmen und das erhärtet meinen - bereits an anderen Stellen gewonnenen - Argwohn gegen DIM für nicht primitive Datentypen (wenn man 'String' so bezeichnen darf).
Als mir die Sache mit dem Stack klar wurde, wurde mir auch klar, dass ein "echtes" char[] (oder sein fb-Bruder ZString) diese Probleme nicht haben (würden).
Aber gerade deshalb hat doch der - eigentlich zwingend notwendige - Weg von Sebastian einen Schönheitsfehler: Den Vorteil von String über ZString (auch '0'er erlaubt), habe ich, zumindest ohne weitere Massnahmen, wieder verloren, .
- Oder irre ich da?
Zuletzt bearbeitet von kawe am 16.11.2012, 15:09, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
Sebastian Administrator

Anmeldungsdatum: 10.09.2004 Beiträge: 5969 Wohnort: Deutschland
|
Verfasst am: 16.11.2012, 14:07 Titel: |
|
|
kawe hat Folgendes geschrieben: | Den Vorteil von String über ZString (auch '0'er erlaubt), habe ich, zumindest ohne weitere Massnahmen, wieder verloren, . |
Ja, das stimmt. Wenn du mit *text auf den ZString-Inhalt zugreifst, wird nur bis zum ersten Nullbyte gelesen. Wenn du Binärdaten im Speicher ablegen möchtest, würde ich eher nicht ZString verwenden, sondern einfach einen Block an UByte-Elementen allozieren:
Code: | Dim As Ubyte Ptr bindata, currentbyte
Dim As Integer f, length, i
f = FreeFile
Open "bratwurst.bmp" For Binary As #f
length = Lof(f)
If (length < 1) Then
Print "Die Datei existiert nicht. Das Beispiel kann daher leider nicht ausgefuehrt werden."
Close #f
Sleep
End
End If
bindata = CAllocate(length)
currentbyte = bindata
For i = 0 To length-1
Get #f, , *currentbyte
currentbyte += 1
Next i
Close #f
Print "Gebe Dateiinhalt als Hex-Ansicht aus:"
Print
Dim As Integer defaultColor = LoWord(COLOR)
Dim As Integer lastColor = 0, column = 1
Color 0: Color defaultColor
currentbyte = bindata
For i = 0 To length-1
If ((*currentbyte = 0) And (lastColor <> 12)) Then
Color 12
lastColor = 12
Else
If ((*currentByte <> 0) And (lastColor <> defaultColor)) Then
Color defaultColor
lastColor = defaultColor
End If
End If
Print Hex(*currentByte, 2);
If (column < 27) Then
Print " ";
column += 1
Else
Print "";
column = 1
End If
currentbyte += 1
Next i
Print ""
DeAllocate bindata
Print
Print "Fertig!"
Sleep
End |
Hier die Beispieldatei: bratwurst.bmp
Viele Grüße!
Sebastian _________________
Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen! |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 16.11.2012, 18:04 Titel: |
|
|
Der Vollständigkeit halber sei die Compileroption -t erwähnt, aber auch nur der Vollständigkeit halber.  |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|