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:

Winamp DSP-Plugin
Gehe zu Seite Zurück  1, 2, 3
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Projektvorstellungen
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
RockTheSchock



Anmeldungsdatum: 04.04.2007
Beiträge: 138

BeitragVerfasst am: 16.10.2013, 14:37    Titel: Antworten mit Zitat

Mein Beispiel sollte zeigen dass -1 eigentlich nicht richtig ist, weil man sich normalerweise nicht darauf verlassen sollte das der String eine bestimmte länge hat. Wenn man mit -4 arbeitet besteht dieses ganze Problem nicht!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 17.10.2013, 06:09    Titel: Antworten mit Zitat

@RockTheSchock: Auf die Gefahr hin, mich zu wiederholen: Wenn du auf diese Weise mit Pointern arbeitest, mußt du sicherstellen, daß der String die richtige Länge hat, und zwar, bevor du anfängst, ihn zu bearbeiten!
Vielleicht kann ich dir das veranschaulichen:
Angenommen, du hast einen String "g" von 8 Byte Länge, der bei Adresse 1000 beginnt
    1000 |
    1001 | 1. Wert
    1002 |
    1003 |__
    1004 |
    1005 | 2. Wert
    1006 |
    1007 |__
    1008 | undefinierter Inhalt
    1009 | undefinierter Inhalt
    1010 | undefinierter Inhalt
    1011 | undefinierter Inhalt
    1012 | undefinierter Inhalt
    ...
Dann hat StrPtr(g) einen Wert von 1000 und Len(g) einen Wert von 8. Und nun halte dir vor Augen, wie eine For/Next-Schleife funktioniert:
    Zuerst wird die Laufvariable auf den Anfangswert gesetzt und die Schleife einmal durchlaufen.
    Dann wird zur Laufvariable die Schrittweite addiert und geprüft, ob dieser Wert größer ist als der Endwert.
    Wenn nicht, wird die Schleife noch einmal durchlaufen, wenn ja, wird das Programm fortgesetzt.
Für unser Beispiel heißt das:
    Anfangswert: StrPtr(g) = 1000
    Schrittweite: SizeOf(Single) = 4
    Endwert: StrPtr(g) + Len(g) - 1 = 1007
    Wert der Laufvariable vor dem 1. Schleifendurchlauf: 1000
    Wert der Laufvariable nach dem 1. Schleifendurchlauf: 1000 + 4 = 1004 ---> 1004 < 1007 ---> Schleife wiederholen
    Wert der Laufvariable nach dem 2. Schleifendurchlauf: 1004 + 4 = 1008 ---> 1008 > 1007 ---> Schleife beenden und Programm fortsetzen
Das wäre der korrekte Ablauf. Bei einer Pointerlänge von 4 Bytes funktioniert das Ganze auch noch bis
    Endwert: StrPtr(g) + Len(g) - 4 = 1004
    ...
    Wert der Laufvariable nach dem 1. Schleifendurchlauf: 1000 + 4 = 1004 ---> 1004 = 1004 ---> Schleife wiederholen
    ...
Aber stell dir vor, du hättest jetzt statt einem SinglePtr einen BytePtr mit einer Länge von 1. Dann würden die letzten 3 Werte des Strings überhaupt nicht gelesen. Wenn andererseits der String eine Länge von 9 Bytes hätte, bekämst du einen weiteren Schleifendurchlauf
    Endwert: StrPtr(g) + Len(g) - 1 = 1008
    ...
    Wert der Laufvariable nach dem 2. Schleifendurchlauf: 1004 + 4 = 1008 ---> 1008 = 1008 ---> Schleife wiederholen
    Wert der Laufvariable nach dem 3. Schleifendurchlauf: 1008 + 4 = 1012 ---> 1012 > 1008 ---> Schleife beenden und Programm fortsetzen
    ...
Wenn du nur lesend auf den Speicher zugreifst, passiert nicht viel, außer, daß du beim letzten Wert Datenmüll bekommst. Solltest du jedoch in die 3 Speicherstellen hinter dem String schreiben, kannst du Glück haben, daß diese gerade nicht benutzt werden, es kann aber auch sein, daß dort eine andere Variable abgelegt ist, beispielsweise ein Integer-Wert, der irgendwo anders im Programm gebraucht wird. Dann veränderst du dessen Inhalt und produzierst damit einen der fiesesten Fehler, die es gibt: Es gibt keine Fehlermeldung und mit hoher Wahrscheinlichkeit auch keinen Programmabsturz, du hast nur plötzlich irgendwo anders einen falschen Wert. Und da beim nächsten Programmstart die Variablen höchstwahrscheinlich an einer anderen Position stehen, ist der Fehler auch nicht reproduzierbar und tritt selten und in unregelmäßigen Abständen auf. Nach sowas kannst du dich monatelang totsuchen.

Wenn du mit den Stringfunktionen arbeitest, sorgt der Compiler dafür, daß es keine verbotenen Speicherzugriffe gibt, das macht die Sache aber auch sehr langsam. Zugriffe über Pointer sind sehr viel schneller, dafür mußt du dich aber selber um die Integrität der Daten kümmern und solltest genau wissen, was du tust. Das hat schon einen Hauch von Assemblerprogrammierung.

Also noch einmal: Du bist für die korrekte Länge des Strings verantwortlich, und der korrekte Endwert für alle Pointerarten ist StrPtr(g) + Len(g) - 1

Gruß
grindstone
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
RockTheSchock



Anmeldungsdatum: 04.04.2007
Beiträge: 138

BeitragVerfasst am: 17.10.2013, 07:55    Titel: Antworten mit Zitat

Zitat:
Aber stell dir vor, du hättest jetzt statt einem SinglePtr einen BytePtr mit einer Länge von 1


Ich habe ja extra geschrieben dass es korrekterweise heißen muss:
-SizeOf(DATENTYP) was bei Single -4 ist bei byte aber -1 und bei Double halt -8
Dadurch ist sichergestellt das egal was an die Funktion übergeben wird kein falscher Speicherbereich überschrieben wird.

Und die beiden For schleifen vor und nach dem Funktionsaufruf dienen lediglich zur Anschaung, zum Gucken was im Speicher passiert.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 18.10.2013, 10:07    Titel: Antworten mit Zitat

@RockTheSchock: Ich habe mir eben alle posts noch einmal durchgelesen und fürchte, daß ich dich die ganze Zeit falsch verstanden habe.

Wenn du ein Programm zu Testzwecken gezielt mit falschen Daten fütterst, um einen Fehler zu provozieren, solltest du das deutlich dazuschreiben. So wie du das formuliert hast, wirkt es so, als ob du nicht wirklich weißt, was du tust und ratlos bist, warum das Programm immer wieder falsche Ergebnisse liefert.

Im übrigen muß ich dir recht geben: -SizeOf(DATENTYP) ist bei fehlerhafter Stringlänge sicher gegen unerwünschte Seiteneffekte durch falsches Schreiben in den Speicher. Daumen rauf!

Gruß
grindstone
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
RockTheSchock



Anmeldungsdatum: 04.04.2007
Beiträge: 138

BeitragVerfasst am: 18.10.2013, 11:29    Titel: Antworten mit Zitat

Zitat:
Ich habe mir eben alle posts noch einmal durchgelesen und fürchte, daß ich dich die ganze Zeit falsch verstanden habe.

Tut mir leid, dass ich mich nicht genau genug ausgedrückt habe. Das war ein gutes Beispiel wie man Konfusion erzeugt, indem man keine vernünftigen Kommentare schreibt. Ich hätte einfach nur einen kleinen Kommentar zu meinem Testcode einfügen müssen und einen Kommentar inderhalb der Funktion ampfloat zur Schleifenabbruchbedingung.

Schon hätten wir uns die halbe Diskussion sparen können.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 19.10.2013, 07:47    Titel: Antworten mit Zitat

Zitat:
Schon hätten wir uns die halbe Diskussion sparen können.

Sieh es mal positiv: Für den einen oder anderen derjenigen, die diesen Thread still im Hintergrund verfolgen, hat das Ganze sicher einen Erkenntnisgewinn gebracht. zwinkern

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Projektvorstellungen Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite Zurück  1, 2, 3
Seite 3 von 3

 
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