Pointer Adresse

Anonymous
2018-05-24
2024-02-01
  • Anonymous - 2018-05-24

    Originally created by: mg

    Hallo Leute
    Wago 750-8202 02.07.07(10)
    Codesys V2.3.9.49

    WOHER KOMMT FOLGENDENS VERHALTEN? WAS KANN ICH DAGEGEN TUN?
    Es soll ein String gemacht werden: STRING(1536),
    Dazu werden String-Schnipsel aneinandergefügt. In jeder 2. Zeile wird dann die Länge des hinzugefügten String-Schnipsels dazuaddiert.
    Die ersten 1200 bytes String-Schnipsel geht alles gut ABER DANN ...
    Es geht um den Pointer PT_str_GNUPLOT_INI. Beachte wie der sich erhöht ...

    Erst mal stoppe ich den Task bevor es interessant wird
    stop

    F8 (eine Zeile vorwärts)

    F8 (eine Zeile vorwärts)

    Siehe PT_str_GNUPLOT = 000000000 (WARUM ??????)
    HINWEIS: das Problem taucht beim Zeilenteil PT_str_GNUPLOT_INI^:=gnuplot_zeile_s;
    HINWEIS: die FUNCTION(nLEN) hat NICHTs damit zu tun (ich bin inzwischen schon weiter beim analyserien)
    Wenn ich nun aus der routine rauskomme passiert folgendes ...

    Und dann F8,F5

    Noch ein paar Hinweise:
    Das Ganze ist in einem Funktionsblock.
    Der Funktionsblock wird von einem PRG aufgerufen, das an einem zyklischen Task (t#1s) hängt.
    Der Funktionsblock wird max 1x pro Zyklus aufgerufen.
    Die Variable PT_str_GNUPLOT_INI ist lokal.

    Danke mg

    PS: ... und weil ich zu DOOF bin und das mit den ins Forum implentierten Bildern nicht kapiert hab kommen nun alle Bilder nochmals.
    ENTSCHULDIGUNG.

    IMG: Bild

    IMG: Bild

    IMG: Bild

    IMG: Bild

    IMG: Bild

    IMG: 5.jpg

    IMG: 4.jpg

    IMG: 3.jpg

    IMG: 2.jpg

    IMG: 1.jpg

     
  • Anonymous - 2018-06-11

    Originally created by: mg

    HIER DER KOMMENTAR VON WAGO

    Sehr geehrter Herr ............,
    wie versprochen habe ich das Verhalten hier im Haus näher analysiert. Dazu habe ich ein einfaches Beispiel erzeugt (siehe Anhang).
    Diese Beispiel mach im Prinzip selbiges wie Ihr großes Projekt.
    Bitte lassen Sie das Beispiel zunächst ohne die AT-Adressierung für den STRING laufen.
    Sie werden sehen das hier ab dem 4. Durchlauf der Pointer eine falsche Adresse erhält und die Werte nicht mehr korrekt an den STRING übergeben werden.

    Ursache ist nach langer Diskussion mit der Entwicklung, dass bei einem STRING, entgegen der Annahme, die Daten im Prozessabbild nicht Byte für Byte linear hintereinander liegen. Das führt dazu, dass auf falsche Adressen geschrieben werden kann. Dies kann u.U. so sein, muss jedoch nicht.
    Dies ist abhängig von der vom Compiler unter der Haube durchgeführten Codeoptimierung, wo WAGO leider keinen Einfluss drauf hat.

    Die Lösung ist jedoch denkbar einfach. Entweder geben Sie dem String eine feste Start- Adresse aus dem Merker-Bereich (so wie in meinem Beispiel) oder arbeiten über eine ARRAY OF BYTE wo Sie die Daten zunächst reinkopieren.
    Begründung ist, dass der Merker-Bereich nicht vom Compiler optimiert wird (alle Adressen linear) und ein ARRAY OF BYTE, egal wo angelegt, sicher alle Daten im Prozessabbild Byte für Byte linear hintereinander liegen.

    Wir empfehlen jedoch die Variante über eine ARRY OF BYTE, da Sie bei der Verwendung von Merkern berücksichtigen müssen, dass weitere Zugriffe in den Merker-Bereich nicht addressüberschneidend erfolgen.

    Ich bedanke mich für dieses Feedback und hoffe damit eine WORKARROUD für Sie geschaffen zu haben.

    UND NUN DIE FRAGE AN CODESYS, IST DAS WAHR
    Ich programmiere sein >10 Jahren diese Controller und nun bekomme ich die Meldung daß bei ALLEN Controllern zT über das Ende eines Strings hinausgeschrieben (oder sonst wo völlig undefiniert hingeschrieben) wird. Ich habe mal nachgerechnet und ich weiß bereits mehr als 100 Controller mit dieser Definition PT_TO_STRING. zT wurden >100 Variablen derart definiert. Ich hoffe mal daß dieses Verhalten nicht überall auftritt aber ich brauche UNBEDINGT ZEITNAHE Informationen was ich nachbearbeiten muß.

    Ich mache das Ganze im Moment mit dem Befehl "SysMemCpy" ich H O F F E daß zumindest dieser Baustein dieses Verhalten nicht zeigt. Die Variante mit dem ARRAY OF BYTE ist vom Aufwand für die Ändungen untragbar.

    PS: Ich habe vor 2 Jahren schon mal über sehr suspekte Pointerfehler berichtet und NICHTS MEHR davon gehört. Bitte schaut Euch auch dieses Thema an vielleicht ist dort das selbe Problem anzutreffen.

    https://forum-de.codesys.com/viewtopic.php?t=4979#p16133

    VIELEN DANK FÜR WEITERE INFORMATIONEN

    Mg

    Ihr könnt mich auch anrufen die Nummer ist hinterlegt. (unter ICQ hinterlegt)

    ReProPointer.zip [7.45 KiB]

     
  • eschwellinger

    eschwellinger - 2018-06-13

    Hallo

    die Daten eines Strings liegen natürlich Byte für Byte hintereinander.

    In dem Beispielcode, sind folgende Variablen definiert:

    sHelper                                : STRING;
    sTest                                     (*AT %MB10000*) : STRING;(* Reproduktion mit 'AT %MW10000' und ohne 'AT %MW10000' *)
    psPointer                            : POINTER TO STRING;
    

    die liegen dann üblicherweise auch so hintereinander, man beachte dass sHelper und sTest die gleiche definierte Grösse haben.
    Wenn man nun die folgende Zuweisung hat:
    psPointer^ := sHelper;
    dann erzeugt der Compiler für diese Zuweisung kein stringcopy bis zur abschliessenden 0 sondern ein memcopy über die volle Länge des definierten Strings.
    Der Compiler sagt: psPointer ist definiert als Pointer TO STRING(80), sHelper ist auch definiert als STRING(80) dann kopieren wir mal die 80 Byte von rechts nach links.
    Wenn man den Pointer sukzessive um einige Bytes weiterschaltet, dann überschreibt der sich eben irgendwann selber.

    Du musst dafür sorgen dass der POINTER immer auf einen genügend großen Speicher zeigt für den Basisdatentyp auf den er definiert ist, sonst läufst du in solche Probleme rein.
    In dem Beispielcode wäre es beispielsweise sinnvoll, den Pointer als POINTER TO STRING(4) zu definieren.
    Du solltest dir überlegen wie gross wird der STRING den er von rechts
    nach links kopieren will und der Pointer sollte auf keinen größeren Bereich zeigen.

    Grüße
    Edwin

     
  • Anonymous - 2018-06-20

    Originally created by: mg

    Hallo Hr. Schwellinger

    Danke für die Antwort. Das habe ich mir bereits gedacht und so war auch meine 1. Lösung
    Nun noch eine Frage: Wenn ich nun zB folgende Zeile schreibe

    Deklaration:
    File_actfile: STRING(255);
    PT_File_actfile: POINTER TO STRING(255);

    Software (Annahme: Der Pointer steht nicht am Anfang des Strings)
    PT_File_actfile^:='.csv';

    Wieviele Bytes werden geschreiben - 4,80,255?
    Ist das zielsystemabhängig?

    Mit bestem Dank

    Mg

     
  • eschwellinger

    eschwellinger - 2018-06-21

    Hallo mg,

    im Prinzip könnten/könnten (plattformabhängig) das die Codegeneratoren unterschiedlich machen,
    ich denke aber dass es alle so machen, dass in diesem Fall 255 Byte kopiert werden.
    Die Logik ist so, dass wir das Minimum der Länge von Zielstring und Quellstring kopieren
    und dann auf Länge + 1 explizit eine 0 schreiben.
    STRING(255) belegt ja 256 Bytes.

    Grüße
    Edwin

     
  • Anonymous - 2018-06-21

    Originally created by: mg

    Hallo Erich

    Sind Sie sich sicher?

    Das würde ja bedeuten, daß ich bei JEDEM Belegen des Strings über einen Pointer, MINDESTENS ein BYTE über die definierte Grenze hinauschreibe. Das würde weiter bedeuten, daß eine Belegung des Strings über einen Pointer NICHT ERLAUBT wäre.

    Faktisch wäre eine Belegung dann nur derart möglich:

    Deklaration:
    File_actfile: STRING(255);
    PT_File_actfile: POINTER TO STRING(255);
    String_Schnipsel_s:=STRING(8);

    Software (Annahme: Der Pointer steht nicht am Anfang des Strings)

    String_Schnipsel_s:='.csv';
    PT_File_actfile^:=String_Schnipsel_s;

    Ist das richtig, was ich hier von mir gebe.
    Ist das in der V3 identisch?

    Mario

    PS: Wenn das wirklich so ist, muß man das aber in der Codesys-Software sperren. Das darf nicht möglich sein!

     
  • eschwellinger

    eschwellinger - 2018-06-27

    Hallo,

    wenn Sie einen POINTER TO STRING(255) definieren, dann sollten Sie immer dafür sorgen dass der auf genügend Speicherplatz zeigt.
    Der Compiler geht davon aus, dass der Pointer auf Speicher der Länge 256 zeigt und verwendet den gesamten Speicher.

    Grüße
    Edwin

     

Log in to post a comment.