CPU Stop wegen Lokaldaten, SCL & Stringoperation

Sinix

Level-1
Beiträge
1.588
Reaktionspunkte
216
Zuviel Werbung?
-> Hier kostenlos registrieren
HI,

wer kann helfen oder einen lösungsbehafteten Link einstellen?

Bekomme einen CPU-Stop mit "Fehler beim Allokieren der Lokaldaten".
Ursache ist offensichtlich das die Grenze der verwendbaren Lokaldaten überschritten wird bei der Verwendung von Stringoperationen wie REPLACE,DELETE,INSERT,LEFT,... in SCL.
Habe derzeit 2 FCs. Beide haben ca. 1000kB Lakaldaten. Alle anderen Bausteine <50kB. Die IM-F-CPU kann wohl 7198kB. Das Problem trat erst bei der Programmierung des zweiten FCs auf, wobei hier eine Stringoperation ca.250kB schluckt und nur eine einzige temporäre Integervariable deklariert ist. Bei den Stringoperationen wird nur auf einen globalen DB zugegriffen. Schachtelungstiefe ist unkritisch.

Was muss ich tun um mit den Stringoperationen in Menge arbeiten zu können?

Vielen Dank im vorraus für Antworten.

MfG MK
 
ohne das gesamte Projekt zu kennen ist es schwer über die gesamte Speichernutzung zu sprechen, deswegen von mir folgender Vorschlag:

- die Stringbearbeitung in einem Baustein
- mehrere Strings zyklusweise versetzt bearbeiten
(- sollte IMHO von der Verarbeitungszeit immer noch reichen, wenn alle ergebnisse erst nach drei oder vier Zyklen zur Verfügung stehen.)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich sehe das wie 4L ... stell doch vielleicht einfach mal den "bösen" FC (mit der String-Bearbeitung) hier ein. Vielleicht gibt es ja Optimierungs-Möglichkeiten ...

Gruß
Larry
 
@4L meinst du statt zwei FC nur einen FC mit Stringoperationen?
Wenn ja, was könnte da der Grund sein dies zu tun?

im Anhang mal der böse FC, zum Verständnis: es soll ein String mit 4 Achspositionen semikolonsepariert zusammengefügt werden, der später per RS232 (ASCII) gesendet wird.

MfG MK
 
@4L meinst du statt zwei FC nur einen FC mit Stringoperationen?
Wenn ja, was könnte da der Grund sein dies zu tun?

ich gehe davon aus, dass deine beiden FCs das selbe machen - richtig? nur eben global adressiert.
dynamisiere das bzw. führe die funktionen parameter-orientiert aus, dadurch sparst du einen baustein und die benötigten lokaldaten werden kleiner. <- das ist der grund
 
Ich bin auch kein Freund von Operationen wie :
Code:
myString := left(myString , len(myString)-4) ;  // unabhängig, ob das nun syntaktisch korrekt ist
bei solchen (oder ähnlichen) Konstrukten neigt SCL schonmal dazu, sich sich Lokaldaten-mäßig auszubreiten - das ist hier aber nur Spekulation. Gut ist auf jeden Fall, wenn der Baustein seine eigenen Zwischen-Variablen erzeugt und verwaltet ...
 
Das Problem hatte auch auch schon einmal.
Die 400-er und auch die 318 (bzw. Speed7) bieten die Möglichkeit, die Größe des Lokaldaten-Stack für die jeweilige Ebene zu ändern. Vielleicht kann das die IM auch, ich glaube aber eher nicht. :confused:

Dann hilft nur, die Funktionen so aufzusplitten, das der Lokaldatenbedarf sinkt. Du kannst mal Teile des Code auskommentieren, dann den Baustein schließen und mit der rechten Maustaste auf dem Baustein die Objekteigenschaften des Bausteins aufrufen. Unter Allgemein-Teil2 sieht man den Lokaldatenbedarf.

Alle temporäre Variablen (TEMP) eines OB und seiner unterlagerten Bausteine werden im L-Stack gespeichert. Wenn Sie viele Schachtelungsebenen in Ihrer Bausteinbearbeitung verwenden, kann der L-Stack überlaufen.

Wenn man also viele Bausteine schachtelt, addiert sich der Lokaldatenbedarf. Es könnt also helfen, Bausteine nacheinander aufzurufen, statt ineinander.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@4L dein Wunsch ist stattgegeben obwohl in mein Arbeitsvertrag irgendwas mit Betriebsgeheimnisse steht. Kannst du mal ein Beispiel reinstellen, was du mit dynamisieren bzw. parameter-orientiert meinst? Der erste FC70 ist zum zerpflücken der empfangenen Daten, der zweite FC71 soll die Antwortdaten zusammensetzen.

@Larry, bin ein Freund solcher Konstrukte, um den Code schlank zu halten. Wenn ich in SCL temporäre Hilfstrings mit 254 Zeichen deklariere gehen die Lokaldaten auch in die Höhe. Wäre dumm wenn SCL das nicht ab kann.

@Ralle, bei IM-CPU kann man wohl nichts an den Stacks ändern, oder? Was sagt die Anzeige, siehe Anhang aus? Wie gesagt die Schachtelungstiefe ist nicht so hoch, maximal 3 oder 4.

Danke schonmal für eure Bemühungen;)
 
Für deine ganzen String-Funktionen werden intern Strings mit der eingestellten Maximallänge von 254 Bytes angelegt, z.B. auch für die erste DINT_TO_STRING Funktion wird erst über eine unsichtbare Temp-Variable gegangen.
Ohne jetzt am Code was zu ändern, könntest du mal nachrechnen wie lang dein String maximal werden kann. Denn so wie es aussieht brauchst du die 254 Zeichen eher selten.
Dann könntest du über die Compileroption
Code:
{ SetMaximumStringLength := '50' }
Die Länge der internen Strings auf z.B. 50 begrenzen. Wenn du jetzt 1000 Byte an Lokaldaten hast (glaub bei dir ist überall ein k zu viel), hättest du damit schonmal nur ein fünftel verbaucht.

Wenn du es in einem FC lassen willst, könnte man dem Compiler noch durch Umstellung auf temporäre Strings mit der entsprechenden Länge etwas unter die Arme greifen (hier gibt es aber ein paar Beschränkungen hinsichtlich IN/OUTs von Funktionen), oder auf einen FB umstellen bei dem die temporären Strings in den statischen Daten abgelegt werden.
 
Ich meinte das hier:

attachment.php


PS: Hab nachgesehen, bei der IM kann man die Stackaufteilung nicht verändern.
 

Anhänge

  • Objekteigenschaften.jpg
    Objekteigenschaften.jpg
    84,5 KB · Aufrufe: 75
Zuviel Werbung?
-> Hier kostenlos registrieren
OK ... Thomas hat nun also bestätigt, was ich schon vermutet hatte ...
Wenn du die Teil-Strings und ggf. Zwischenvariablen selbst anlegst und nicht SCL die Initiative überläßt dann kannst du selbst beeinflussen, wie groß die Variablen werden.
Das mit den Compiler-Options würde ich nicht unbedingt machen, weil du es ggf. im nächsten Projekt wieder anders brauchst ... Da wären dann deklarierte Variablen einfach besser.

@MK:
Dein Code ist nun zwar schön schlank (im SCL-Bereich) - es kann aber halt sein, dass er im AWL-Bereich (und zu so etwas wird es dann ja) regelrecht explodiert. Das muss man m.E. immer ein bißchen im Auge behalten.

Du könntest es aber auch in etwa so machen :
Code:
myTempString := left(myString,4) ;
myString := right(myTempString,4) ;
Gruß
Larry
 
Das mit den Compiler-Options würde ich nicht unbedingt machen, weil du es ggf. im nächsten Projekt wieder anders brauchst ... Da wären dann deklarierte Variablen einfach besser.
Und wo ist jetzt der Unterschied im Ändern der Konstante bei den Compileroptionen und ändern einer konstanten Stringlänge? Stehen doch beide in der gleichen Quelldatei. Außerdem hast du mit der Angabe der Länge der temp-Strings immer noch keine Kontrolle über die Länge der 'unsichtbaren' Strings.

Die Frage ist aber auch, warum der SCL-Compiler hier mal wieder strunzdoof ist.
Es gibt eigentlich keinen Grund bei der Zeile
Code:
Daten_an_extern.String_PosX1 := DINT_TO_STRING(MD300);
erst über einen unsichtbaren Temp-String zu gehen und diesen dann per Blockmove in den Datenbaustein zu kopieren. Evtl. gibt es hier ja noch einen Trick wie man den Compiler doch noch dazu überlisten kann direkt auf den DB zu schreiben, ich habs nicht hinbekommen.

Ich würde einfach von einem FC auf einen FB wechseln und die temporären Strings in den statischen Variablen des FBs anlegen. Hier hat man auch bei den kleinsten CPUs eigentlich immer ausreichend Platz.
Denn wenn ich das obige in einem FB mache mit Ziel auf eine statische Variable, komme ich ganz ohne den Lokaldatenverbrauch aus.
Code:
FUNCTION_BLOCK FB701
VAR
    str1 : STRING;
END_VAR

BEGIN
    str1 := DINT_TO_STRING(MD300);
    Daten_an_extern.strTest := str1;
END_FUNCTION_BLOCK

Als allgemeine Empfehlung kann man vielleicht stehen lassen, dass man bei Stringverarbeitung möglichst absolute Datenbausteinzugriffe vermeiden sollte. Also möglichst lange auf temporären oder statischen Daten arbeiten, und erst ganz zum Schluss den internen String auf den Datenbaustein kopieren.
 
Und wo ist jetzt der Unterschied im Ändern der Konstante bei den Compileroptionen und ändern einer konstanten Stringlänge? Stehen doch beide in der gleichen Quelldatei. Außerdem hast du mit der Angabe der Länge der temp-Strings immer noch keine Kontrolle über die Länge der 'unsichtbaren' Strings.
Der Unterschied ist für mich, dass du es für alle Projekte, die du machst dann so festgelegt hast. Im Unterschied dazu gilt der deklarierte String nur dort, wo er deklariert wurde ...

Ich muss allerdings gestehen, dass ich es als "alter" Pascal-Programmierer auch gewohnt bin, mit deklarierten Variablen zu arbeiten (ob die dann immer einen tollen Namen haben ist eine andere Sache :rolleyes:).

Als allgemeine Empfehlung kann man vielleicht stehen lassen, dass man bei Stringverarbeitung möglichst absolute Datenbausteinzugriffe vermeiden sollte. Also möglichst lange auf temporären oder statischen Daten arbeiten, und erst ganz zum Schluss den internen String auf den Datenbaustein kopieren.
*ACK* und kein Einwand ... Es so zu machen ist m.E. ja auch der eigentliche Sinn von SCL ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Unterschied ist für mich, dass du es für alle Projekte, die du machst dann so festgelegt hast. Im Unterschied dazu gilt der deklarierte String nur dort, wo er deklariert wurde ...
Nein, die Compileroptionen gelten nur in der Quelldatei in der diese angegeben sind.
Fehlt in Quelldateien eine Option, so werden die global gültigen Werte angenommen die unter Menü -> Extras -> Einstellungen -> Compiler stehen.
Die maximale Stringlänge würde ich hier jedoch niemals verändern, da diverse Bausteine auch bei fehlender Option davon ausgehen dass hier die Maximal-Länge 254 drinsteht.

Ich habe normalerweise pro Baustein eine SCL-Quelle. Also gelten die Einstellungen auch nur für diesen einen Baustein.
 
Compiler-Option - Klar ... habe ich glatt überlesen. Dann ist das natürlich korrekt !!!
Ich hatte das so verstanden, dass du das mit Extra's-Einstellungen-etc. meintest ...
 
Habe nun etwas rumprobiert und es ist wohl tatsächlich so, dass bei Verwendung von statischen String-Variablen und Stringoperationen in einem FB die Lokaldaten minimiert werden. Eine am Bausteinende befindliche Zuweisung des Strings zum globalen DB wie Thomas vorgeschlagen hat, hat keine Erhöung der Lokaldaten zur Folge.

Danke allen die geholfen haben.:s17:

MfG MK
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hab das mal "überflgen"

Mach aus deiner FC nen FB und nutze die statischen Variablen für deine Strings! Nicht die Temporären!!! Dann klappt's auch mit den Strings.

Du kannst aber auch in der CPU in den CPU Eigenschaften (HW-Konfig) im Register Speicher der CPU "schrauben". Da solltest du aber wissen was du machst!
 
Mach aus deiner FC nen FB und nutze die statischen Variablen für deine Strings! Nicht die Temporären!!! Dann klappt's auch mit den Strings.
In seinem Ursprungsprogramm benutzt er doch gar keine temporären Variablen. Der Verbrauch geht allein durch die verschiedenen Stringfunktionen und die Verwendung in SCL so hoch. Und das auch grundlos. Lies dir den Thread vlt. nochmal im genauer durch.
 
Wenn du mit ner FC arbeitest wird alles speicherrelvante in den Lokaldaten gemacht.
Hab auch schon viel mir Strings in SCL gemacht und bin da an die gleichen Grenzen gestossen.
Wenn ich mal Luft habe les ich mir das durch. Wollte nur nen schnellen Lösungsansatz bringen.
 
Zurück
Oben