Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Ungültige Zeigeroperation

73 views
Skip to first unread message

Stefan Koschke

unread,
Mar 8, 2011, 1:41:23 AM3/8/11
to
Hallo zusammen,

nachdem mein Programm 15 Stunden aktiv ist und folgende Zeile tausende
mal durchlaufen wurde, bekomme ich plötzlich

"Ungültige Zeigeroperation" bei folgendem Code

compuffer := '';

Ich habe nicht die geringste Ahnung wo ich da suchen soll!

Hat jemand eine Idee?

Ciao
Stefan

Markus Springweiler

unread,
Mar 8, 2011, 4:01:52 AM3/8/11
to
Hallo Stefan,

> "Ungültige Zeigeroperation" bei folgendem Code
> compuffer := '';
> Ich habe nicht die geringste Ahnung wo ich da suchen soll!

Definitiv bei den anderen Bestandteilen der Schleife.

Du solltest entweder mehr Code zeigen, oder versuchen mit MemProof oder
FastMM dem bereits im Vorfeld entstandenem fehlerhaften schreibenden
Speicherzugriff auf die Schliche zu kommen.

--
/\/\arkus.

Markus Wichmann

unread,
Mar 8, 2011, 4:33:55 AM3/8/11
to

Hmmm... was ist compuffer? Ein String?

Davon abgesehen, denke ich nicht, dass das das Problem ist. Vermutlich
ist der Code irgendwo anders kaputt und obige Zeile löst nur das Symptom
aus. Meine Vermutung wäre ein Buffer Overflow irgendwo, der eine
Verwaltungsstruktur von Delphi zerstört. Viel Spaß beim Suchen!

Tschö,
Markus

Stefan Koschke

unread,
Mar 8, 2011, 6:27:31 AM3/8/11
to
Hallo Markus,

genau dabei bin ich ja ;-)
compuffer ist ein AnsiString, an den im Programm nur Zeichen hinten
angehängt werden und der dann an anderen Stellen im Code von vorn her
verarbeitet wird. Nach der Verarbeitung der darin befindlichen Zeichen
wird er gelöscht (die benannte Fehlerzeile).

compuffer ist im Formular unter Private deklariert, es gibt mehrere
dieser Formulare die parallel (Timergesteuert, keine Threads) arbeiten.

Das Ganze geht mitunter Tagelang gut, aber dann mal der hier gemeldete
Fehler.

Aus diesen Zusatzinfos, hast Du jetzt eine Idee wo ich ansetzen könnte?

Ciao
Stefan

Markus Springweiler

unread,
Mar 8, 2011, 7:01:28 AM3/8/11
to
Hallo Stefan,

> es gibt mehrere
> dieser Formulare die parallel (Timergesteuert, keine Threads) arbeiten.

Ist sichergestellt, dass die Liste aller Formulare auch wirklich nur die
lebendigen, also nicht ge-Free-ten, enthält?

--
/\/\arkus.

Bernd Gilles

unread,
Mar 8, 2011, 7:28:29 AM3/8/11
to
Am 08.03.2011 13:01, schrieb Markus Springweiler:
>> es gibt mehrere
>> dieser Formulare die parallel (Timergesteuert, keine Threads) arbeiten.
>
> Ist sichergestellt, dass die Liste aller Formulare auch wirklich nur die
> lebendigen, also nicht ge-Free-ten, enthält?

Da die Variable im Formular private ist, wird ja nicht von aussen darauf zugegriffen werden.

Der eigentliche Verursacher der Zugriffsverletzung dürfte etwas weiter vorne im Code liegen, darum
dürfte uns Deine bereits geäusserte Bitte um etwas mehr Code hier eher weiterbringen ;-)


--
Gruß, Bernd
---
Access goes Subversion - http://oasis.dev2dev.de

Markus Springweiler

unread,
Mar 8, 2011, 8:14:17 AM3/8/11
to
Hallo Bernd,

> Da die Variable im Formular private ist, wird ja nicht von aussen darauf zugegriffen werden.

Das nicht. Aber eine Instanz-Methode ist immer aufrufbar: Erst wenn sie auf
Felder zugreift, kracht es. Deswegen funktioniert auch TObject.Free()
(welches mittels Self aber nur feststellen kann, ob die Referenz nil ist,
und nicht ob die Instanz noch gültig ist).

--
/\/\arkus.

Bernd Gilles

unread,
Mar 8, 2011, 8:21:59 AM3/8/11
to

stimmt auch wieder ;-)

Aber etwas mehr Code könnte trotzdem ein bisschen Licht ins Dunkel bringen.

Stefan Koschke

unread,
Mar 8, 2011, 8:24:47 AM3/8/11
to
Am 08.03.2011 13:01, schrieb Markus Springweiler:
ich denke, ja, alle (max 8) Formulare werden bei Programmstart erzeugt
und bei Programmende zerstört.

Ciao
Stefan

Stefan Koschke

unread,
Mar 8, 2011, 8:30:22 AM3/8/11
to
Am 08.03.2011 13:28, schrieb Bernd Gilles:
> Am 08.03.2011 13:01, schrieb Markus Springweiler:
>>> es gibt mehrere
>>> dieser Formulare die parallel (Timergesteuert, keine Threads) arbeiten.
>>
>> Ist sichergestellt, dass die Liste aller Formulare auch wirklich nur die
>> lebendigen, also nicht ge-Free-ten, enthält?
>
> Da die Variable im Formular private ist, wird ja nicht von aussen darauf
> zugegriffen werden.
>
> Der eigentliche Verursacher der Zugriffsverletzung dürfte etwas weiter
> vorne im Code liegen, darum dürfte uns Deine bereits geäusserte Bitte um
> etwas mehr Code hier eher weiterbringen ;-)
>
>
klar, kein Problem, das Ganze sieht etwa so aus:

if length(compuffer) <> 0 then begin
// Daten in Telemetrieclass sammeln
TeleData.Adddata(compuffer);
compuffer := ''; //leeren weil Daten verarbeitet sind
end;

Ich sehe da nichts "Schlimmes", das Prüfen der Länge des Puffers geht ja
noch.
Teledata ist ebenfalls Private deklariert und eine eigene Klasse

TeleData: Tteledaten;

die im Create des Formulars erzeugt und im Destoy wieder zerstört wird.

Ciao
Stefan

Stefan M. Huber

unread,
Mar 8, 2011, 9:01:57 AM3/8/11
to
Am 08.03.2011, 14:24 Uhr, schrieb Stefan Koschke
<stefan....@t-online.de>:

Sicher? Lass dir mal von den Destroys der Formulare eine Nachricht
ausgeben.

Stefan

Hans-Peter Diettrich

unread,
Mar 8, 2011, 9:12:02 AM3/8/11
to
Stefan Koschke schrieb:

> klar, kein Problem, das Ganze sieht etwa so aus:
>
> if length(compuffer) <> 0 then begin
> // Daten in Telemetrieclass sammeln
> TeleData.Adddata(compuffer);
> compuffer := ''; //leeren weil Daten verarbeitet sind
> end;

Nach meiner Erfahrung mit älteren Delphi-Versionen liegt die Exception
*vor* der angegebenen Zeile. Dann könnte auch TeleData oder irgendwas in
AddData der Verursacher sein.

Zudem hat sich bislang als einfacher (und schneller) herausgestellt:
if compuffer <> '' then ...
weil
length(compuffer)
tatsächlich nach der gespeicherten Länge sucht und dabei zuerst
feststellen muß, ob die Referenz nicht Nil ist.

DoDi

Georg Hübner

unread,
Mar 8, 2011, 10:15:17 AM3/8/11
to
Hallo,

> klar, kein Problem, das Ganze sieht etwa so aus:
>
> if length(compuffer) <> 0 then begin
> // Daten in Telemetrieclass sammeln
> TeleData.Adddata(compuffer);
> compuffer := ''; //leeren weil Daten verarbeitet sind
> end;

Was genau passiert in "TeleData.Adddata(compuffer)"?
Werden dort irgendwelche Objekte angelegt, und/oder Speicher nicht
richtig 'gehandelt'?

Codebeispiel wäre hilfreich. :-)


Mfg

Georg Hübner

Rudy Velthuis

unread,
Mar 8, 2011, 4:46:01 PM3/8/11
to
Stefan Koschke wrote:

> klar, kein Problem, das Ganze sieht etwa so aus:
>
> if length(compuffer) <> 0 then begin
> // Daten in Telemetrieclass sammeln
> TeleData.Adddata(compuffer);
> compuffer := ''; //leeren weil Daten verarbeitet sind
> end;
>
> Ich sehe da nichts "Schlimmes",

Was macht AddData? Wie ist es deklariert? Wenn compuffer als const
übergeben wird und danach gelöscht wird, kann AddData möglicherweise
eine ungültige Referenz speichern.

Aber ich vermute, wenn das das Problem wäre, würde der Fehler viel eher
auftreten. Kann es sein, dass der Speicher knapp wird, oder dass
Windows nach einigen Tagen Zicken macht?

Übrigens,

if compuffer <> '' then

ist schneller als

if length(compuffer) <> 0 then

<> '' vergleicht compuffer direkt mit nil, aber length(compuffer) muss
erst vergleichen mit nil, und wenn nicht, dann das längenfeld lesen.

--
"A computer lets you make more mistakes faster than any invention
in human history – with the possible exceptions of handguns and
tequila." -- Mitch Radcliffe

Stefan Koschke

unread,
Mar 9, 2011, 2:23:57 AM3/9/11
to

Hallo DoDi,

danke für den Hinweis, das werde ich natürlich ausprobieren.
Übrigens läuft das Programm seit gestern Nachmittag wieder
ununterbrochen ohne jegliche Fehlermeldung, da macht Fehlerursache
suchen so richtig Spaß :-(

Ciao
Stefan

Stefan Koschke

unread,
Mar 9, 2011, 2:27:14 AM3/9/11
to

Hier ein Codeschnipsel, wie man sieht wird der Inhalt des compuffer als
const übergeben und dann nach Übergabe in D weiterverarbeitet.
Es gibt nur normale lokale Variablen, es wird nichts erzeugt oder
zerstört...

procedure Tteledaten.AddData(const data: ansistring);
var
D: ansistring;
dt: integer;
dl: integer;
source: ansistring;
daten: ansistring;
dp: integer; // Datenpointer im Array
e1: integer;
begin
if data = '' then
exit;
D := data;
// die übergebenen Daten werden auseinandergenommen und entweder eine
neue Message
// erzeugt oder weitere Daten an eine vorhandene Message angehängt
// dabei wird er Zeitpunkt aktualisiert
// Am Schluß werden zu alte Daten gelöscht und der Arrayeintrag
freigegeben
dp := 0;
while length(D) > 3 do
begin
dt := ord(D[1]); // Datentyp 0=Source, 1=Daten
dl := (ord(D[3]) * 256) + ord(D[2]); // Datenlänge
delete(D, 1, 3);
case dt of
.....

Ciao
Stefan

Stefan Koschke

unread,
Mar 9, 2011, 2:28:51 AM3/9/11
to
Hallo Namensvetter,

ok, mach ich, bin mir aber recht sicher daß das korrekt abläuft.

Ciao
Stefan

Nicole Wagner

unread,
Mar 11, 2011, 10:46:34 AM3/11/11
to
Stefan Koschke wrote:


> Aus diesen Zusatzinfos, hast Du jetzt eine Idee wo ich ansetzen
> könnte?


ja: an einem Log-File.

Portioniere es in Stunden und lasse Dir die relevanten Infos / Var
hineinschreiben. Wenn der Fehler wieder auftritt, liest Du dort nach
und bist schlauer.


Nicole

0 new messages