Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Wie groß dürfen denn Strings nun wirklich sein?

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
kawe



Anmeldungsdatum: 25.03.2012
Beiträge: 41

BeitragVerfasst am: 16.11.2012, 01:23    Titel: Wie groß dürfen denn Strings nun wirklich sein? Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
ALWIM



Anmeldungsdatum: 08.08.2006
Beiträge: 1048
Wohnort: Niederbayern

BeitragVerfasst am: 16.11.2012, 02:04    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 16.11.2012, 02:32    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 16.11.2012, 12:20    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
kawe



Anmeldungsdatum: 25.03.2012
Beiträge: 41

BeitragVerfasst am: 16.11.2012, 13:20    Titel: Antworten mit Zitat

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, traurig.

- Oder irre ich da?


Zuletzt bearbeitet von kawe am 16.11.2012, 15:09, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 16.11.2012, 14:07    Titel: Antworten mit Zitat

kawe hat Folgendes geschrieben:
Den Vorteil von String über ZString (auch '0'er erlaubt), habe ich, zumindest ohne weitere Massnahmen, wieder verloren, traurig.

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
MOD
Fleißiger Referenzredakteur


Anmeldungsdatum: 10.09.2007
Beiträge: 1003

BeitragVerfasst am: 16.11.2012, 18:04    Titel: Antworten mit Zitat

Der Vollständigkeit halber sei die Compileroption -t erwähnt, aber auch nur der Vollständigkeit halber. zwinkern
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
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.

 Impressum :: Datenschutz