Fehler nach NewPrinterPage()

Für allgemeine Fragen zur Programmierung mit PureBasic.
Dieter
Beiträge: 22
Registriert: 14.08.2014 14:32
Computerausstattung: MacMini (2018 (2020), I7 3.2GHz, 32GB), OSX 10.15.5, PB 5.61 x64 - VmWare-Fusion: Win10 Home Premium, XP Professional
History: ZX81 - ZX Spectrum - Apple II - Atari ST - PC (MS-DOS 3.2 ... WIN 10) - Linux/UNIX - Mac

Re: Fehler nach NewPrinterPage()

Beitrag von Dieter »

Hallo Shardik,
ich habe selbstverständlich auch deinen Code ausprobiert. Allerdings bekomme ich bei DirectoryEntryName() nur mit
aktivierter Unicode-Option Dateinamen mit Umlauten geliefert. Deshalb konnte ich ihn dann leider doch nicht verwenden.
Gruß
Dieter
MacMini (2020, I7 3.2GHz, 32GB), OSX 10.15.x, PB 5.72 LTS x64 - VmWare-Fusion: Win7 Home Premium, XP Professional, Ubuntu 14.04 - ZX81 - Apple II - Atari ST
Benutzeravatar
Sicro
Beiträge: 969
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Fehler nach NewPrinterPage()

Beitrag von Sicro »

@Shardik:

Ich habe dich ja schon auf den doppelt großen Buffer hingewiesen, der per Space() in deinem Code erzeugt wird.
Damit du ts-soft und mich besser verstehst, habe ich kurz einen Code erstellt, der die Problematik klar veranschaulichen sollte.
Führe diesen Code im Unicode-Modus aus und schau dir die Debug-Ausgabe an:

Code: Alles auswählen

Define.s Text, Buffer, Output
Define.i BufferSize, i

;Text = "hr"
Text = "hallo"

Buffer = Space(StringByteLength(Text, #PB_Ascii))
BufferSize = StringByteLength(Buffer) + SizeOf(Character)
Debug "Buffer-Größe: " + BufferSize + " Bytes"
Debug "Variable-Inhalt: " + Text
Debug ""

For i = 0 To BufferSize-1
  Select PeekB(@Buffer + i)
    Case 32: Output + "[Leerzeichen]"
    Case  0: Output + "[Null]"
  EndSelect
Next
Debug "Buffer-Inhalt: " + Output 
Debug "Wie man sieht, wird zu viel Buffer reserviert und an jedem Leerzeichen noch ein Null-Zeichen angefügt."
Debug "Korrekt wäre:"
Output = ""
For i = 1 To Len(Text)
  Output + "[Leerzeichen]"
Next
Output + "[Null]"
Debug "Buffer-Inhalt: " + Output
Debug ""

Debug "Wir füllen den Buffer nun mit dem Inhalt der Text-Variable:"
PokeS(@Buffer, Text, -1, #PB_Ascii)
Output = ""
For i = 0 To BufferSize-1
  Byte = PeekB(@Buffer + i)
  Select Byte
    Case 32: Output + "[Leerzeichen]"
    Case 0:  Output + "[Null]"
    Default: Output + Chr(Byte)
  EndSelect
Next
Debug "Buffer-Inhalt: " + Output
Debug "Korrekt wäre:"
Output = Text
Output + "[Null]"
Debug "Buffer-Inhalt: " + Output
Debug ""
Debug "String-Länge mit PB-Len(): " + Len(Buffer)
Debug "Zeichen mit PB-Mid(): " + Mid(Buffer, 1)
Debug "Zeichen mit PB-Left(): " + Left(Buffer, 1)
Debug "Zeichen mit PB-Right(): " + Right(Buffer, 1)
Debug ""
Debug "Es gibt sicherlich noch weitere Funktionen, die eine falsche Ausgabe geben."
Debug "Diese sollten jedoch zur Darstellung der Problematik genügen."
Als Debug-Ausgabe erhalte ich mit eingeschaltetem Unicode-Modus:

Code: Alles auswählen

Buffer-Größe: 12 Bytes
Variable-Inhalt: hallo

Buffer-Inhalt: [Leerzeichen][Null][Leerzeichen][Null][Leerzeichen][Null][Leerzeichen][Null][Leerzeichen][Null][Null][Null]
Wie man sieht, wird zu viel Buffer reserviert und an jedem Leerzeichen noch ein Null-Zeichen angefügt.
Korrekt wäre:
Buffer-Inhalt: [Leerzeichen][Leerzeichen][Leerzeichen][Leerzeichen][Leerzeichen][Null]

Wir füllen den Buffer nun mit dem Inhalt der Text-Variable:
Buffer-Inhalt: hallo[Null][Leerzeichen][Null][Leerzeichen][Null][Null][Null]
Korrekt wäre:
Buffer-Inhalt: hallo[Null]

String-Länge mit PB-Len(): 5
Zeichen mit PB-Mid(): 慨汬o  
Zeichen mit PB-Left(): 慨
Zeichen mit PB-Right():  

Es gibt sicherlich noch weitere Funktionen, die eine falsche Ausgabe geben.
Diese sollten jedoch zur Darstellung der Problematik genügen.

Code: Alles auswählen

Buffer-Größe: 6 Bytes
Variable-Inhalt: hr

Buffer-Inhalt: [Leerzeichen][Null][Leerzeichen][Null][Null][Null]
Wie man sieht, wird zu viel Buffer reserviert und an jedem Leerzeichen noch ein Null-Zeichen angefügt.
Korrekt wäre:
Buffer-Inhalt: [Leerzeichen][Leerzeichen][Null]

Wir füllen den Buffer nun mit dem Inhalt der Text-Variable:
Buffer-Inhalt: hr[Null][Null][Null][Null]
Korrekt wäre:
Buffer-Inhalt: hr[Null]

String-Länge mit PB-Len(): 1
Zeichen mit PB-Mid(): 牨
Zeichen mit PB-Left(): 牨
Zeichen mit PB-Right(): 牨

Es gibt sicherlich noch weitere Funktionen, die eine falsche Ausgabe geben.
Diese sollten jedoch zur Darstellung der Problematik genügen.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Fehler nach NewPrinterPage()

Beitrag von ts-soft »

Einfache Sache: Wir kompilieren im Unicode-Modus, das heißt alle Strings sind im Unicode-Modus, es gibt
keine Strings neben mir.

Code: Alles auswählen

ASCIIText = Space(StringByteLength(Text, #PB_Ascii))
@ASCIIText könnte als Buffer für ASCII dienen, aber ASCIIText.s ist nicht mehr nutzbar!

Du übergibst ASCIIText.s an DrawText(...), welches ungültig sein könnte, da nur Unicode-Strings verwaltet
werden. Den Buffer dürftest Du übergeben, aber der wird ja von DrawText() nicht erwartet.

Okay, der Stringmanager merkt es nicht, da keine Aktion und die defekte API auch nicht, so funktioniert der
Code, mehr oder weniger, zufällig.

Also: Für Buffer anderer Encoding besser Speicher verwenden. Wenn Buffer per Spaces genutzt wird, dann
nur den Buffer nutzen und niemals den String!

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Shardik
Beiträge: 752
Registriert: 25.01.2005 12:19

Re: Fehler nach NewPrinterPage()

Beitrag von Shardik »

Vielen Dank Sicro, für Dein tolles ausführliches Beispiel, das alles wunderbar klar macht und Danke an Thomas für Deine zusätzlichen Erläuterungen.

Der Grund für den "Missbrauch" eines Unicode-Strings war einfach meine Bequemlichkeit: ich brauche keinen Speicherpuffer mit AllocateMemory() anlegen und vor allem später nicht daran denken, diesen wieder freizugeben. Mein Denkfehler lag darin, dass StringByteLength(String, #PB_Ascii) ja korrekt die Länge eines ASCII-Strings angibt, aber Space(StringByteLength(Text, #PB_Ascii)) ja doch wieder im Unicode-Modus die doppelte benötigte Länge anlegt. Dass man mit einem ASCII-String im Unicode-Modus keine String-Operationen durchführen kann, war mir natürlich klar.

In einem früheren Beispiel im englischen Forum hatte ich daher auch im Unicode-Modus die ermittelte Länge für Space() durch 2 dividiert:

Code: Alles auswählen

CompilerIf #PB_Compiler_Unicode
  ASCIIText = Space(StringByteLength(Text, #PB_Ascii) / 2)
  PokeS(@ASCIIText, Text, -1, #PB_Ascii)
CompilerElse
  ASCIIText = Text
CompilerEndIf
Was haltet ihr davon? Die Länge des "missbrauchten" Unicode-Strings ASCIIText ist dann korrekt und der Buffer-Inhalt in Sicros Beispiel wäre dann auch im Unicode-Modus hinterher korrekt. Natürlich ist klar, dass mit der Space()-Funktion im Unicode-Modus der String ASCIIString nicht mit einem korrekten ASCII-String gefüllt ist, aber er dient ja auch nur als Speicherpuffer in der benötigten Größe. Und natürlich funktionieren die String-Operationen nicht, aber man würde ja auch mit einem Speicher-Puffer keine String-Operationen durchführen wollen. Natürlich würde der Einwand von Thomas noch immer gelten, dass DrawText() keinen Buffer erwartet sondern einen String, aber es funktioniert ja trotzdem. Zugegebenermaßen würden Probleme auftreten, wenn Fred den Stringmanager in neueren PB-Versionen verändern oder "schärfere" Prüfungen einbauen würde...
Benutzeravatar
Sicro
Beiträge: 969
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Fehler nach NewPrinterPage()

Beitrag von Sicro »

Shardik hat geschrieben:

Code: Alles auswählen

ASCIIText = Space(StringByteLength(Text, #PB_Ascii) / 2)
So ist es schon viel besser. Im Buffer ist dann nur noch maximal ein Byte zu viel, wenn die String-Länge eine geradene Zahl ist.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Antworten