simple Wertübergabe funktioniert nicht

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

Hallo an Alle!

Bin neu hier im Forum aber ein alter Delphianer.
(Möchte jetzt verstärkt Lazarus nutzen weil sich Emberacedero "oder so ähnlich" ja mit ihrer Produktpolitik bekanntermaßen seit Jahren selbst ins Knie schiessen, aber egal)

Folgendes:

Code: Alles auswählen

 
type myrange = -10..10;
 
type Tconnect=record
  public
  con_nummer:word;
  conned_myObj:word;
  conned_inmyObj:word;
  conned_outmyObj:word;
  conned_io_put:word;
  conned_io_put_in:word;
  conned_io_put_out:word;
  wert:myrange;
end;
 
type Tio_put=record
     public
        nummer:word;
        name:string;
        wert:myrange;
        connection:array of Tconnect;
end;
 
type TmyObj=class
    public
    myObj_nummer:word;
    myObj_name:string;
    myObj_type:byte;
    anzahl_inputs:byte;
    anzahl_outputs:byte;
    inputliste:array of Tio_put;
    outputliste:array of Tio_put;
    constructor create; virtual; abstract;
    procedure grab_input(myObjnummer:word); virtual; abstract;
    procedure calc(myObjnummer:word); virtual; abstract;
end;
 
type TmyObj2=class(TmyObj)
        const myObj_type=11;
        public
                constructor create; override;
                procedure grab_input(myObjnummer:word); override;
                procedure calc(myObjnummer:word); override;
                destructor destroy;
        end;                                   
 
procedure TmyObj2.calc(myObjnummer:word);
var I_1, I_2,calc:myrange;
    i,j:word;
begin
    I_1:=0;I_2:=0;
        I_1:=myObjs_liste[myObjnummer].inputliste[0].wert; //<----- .wert immer wie erwartet aber Fehler: I_1 ist nicht immer .wert
        I_2:=myObjs_liste[myObjnummer].inputliste[1].wert; //<----- .wert immer wie erwartet aber Fehler: I_2 ist nicht .wert sondern irgendeine Zahl
 
 


Auch wenn ich I_1 und I_2 initialisiere, also z.B. mit 0, bekomme ich nach der Zuweisung für I_2 meistens irgendeine sehr hohe Zahl.
Ich kann dies im Debugger nachvollziehen, .wert ist richtig aber I_2 wird nicht zugewiesen.

In der weiteren Verwendung von I_1 und I_2 i.d. vereinfachten Art calc:=max(I_1,I_2); gibts natürlich einen ERangeCheck weil max(calc)=10 sein muss.

Initialisiere ich die Werte kann ich nicht mehr nachvollziehen ob I_2 richtig ist oder nur der vorinitialisierte Wert.

Wieso funktioniert hier die Wertübergabe nicht :?: Bin ich blind? :|
Gleicher Code funktioniert in TurboDelphi (BP 2006), stammt ja auch daher, und funktionierte schon mal in Lazarus.

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: simple Wertübergabe funktioniert nicht

Beitrag von marcov »

Und mit alle rangechecks an compiliert?

-CRriot oder so? Von Compiler wechseln bringt oft verborgenen Bugs nach oben.

Anders: Problem reduzieren bis das minimale Programm der den unerwünschter Verhalten noch hat. (und das dann auch mit Delphi testen, auch da alle Rangechecks an)

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: simple Wertübergabe funktioniert nicht

Beitrag von wp_xyz »

Leider fehlt in deinen Angaben einiges, so dass man wieder mal die berühmte Kristallkugel hervorholen muss: Was ist "myObjs_liste"? Sind alle Objekt-Instanzen ordnungsbemäß erzeugt? Falls myObjs_liste[myObjnummer].inputliste die "inputliste" von TMyObj ist, hast du "SetLength" aufgerufen, um das Array zu dimenionieren?

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

-Criot und -CR
keine Optimierungen
COPERATORS ON (wofür eigentlich ???)
-Si, {INLINE ON}
-Sh, {$H+}
Ziel-OS Win32 und -WG (arbeite hier auf einem Win8.1 Pro 64, das TurboDelphi lief aber auf einem WinXP Pro 32, vielleicht deswegen?)

wenn ich was davon falsch habe oder nicht brauche, ich nehme gerne jeden Hinweis auf

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

wp_xyz hat geschrieben:Leider fehlt in deinen Angaben einiges, so dass man wieder mal die berühmte Kristallkugel hervorholen muss: Was ist "myObjs_liste"? Sind alle Objekt-Instanzen ordnungsbemäß erzeugt? Falls myObjs_liste[myObjnummer].inputliste die "inputliste" von TMyObj ist, hast du "SetLength" aufgerufen, um das Array zu dimenionieren?


Code: Alles auswählen

 
myObjs_liste:array of TmyObj;
 
und viel weiter unten
if length(myObjs_liste[myObj_in-1].inputliste[myObj_in_in].connection)=0
                then    setlength(myObjs_liste[myObj_in-1].inputliste[myObj_in_in].connection,1);
 


Sollte doch aber nicht das Problem sein, da ich im Debugger ja sehe, das bei beiden Zuweisungen "].wert" den korrekten Wert anzeigt. Oder doch? Vor allem, weil TurboDelphi sich nicht dran stört. Selbst bei allen eingeschalteten Warnungen und Hinweisen bekomme ich keine Ansage vom Compiler.

edit:

Code: Alles auswählen

 
constructor TmyObj2.create;
begin
    inherited;
    anzahl_inputs:=1;
    anzahl_outputs:=0;
    setlength(inputliste,anzahl_inputs);
end;
 

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

das mit den Objekten scheint auch unerheblich, denn anscheinend funktioniert nichtmal

Code: Alles auswählen

 
if (I_1=1) then calc:=-1;
 


innerhalb der TmyObj.calc Methode.

I_1 ist laut Debugger an der Stelle definitiv =1, jedoch wird calc nach obiger Anweisung z.B. =5689599 angezeigt.

Was für ein Unsinn!

edit:
nicht mal die Initialisierung per

Code: Alles auswählen

 
procedure TmyObj2.calc(myObjnummer:word);
var I_, calc:myrange;
    i,j:word;
begin
    calc:=0;
    ...
 


funktioniert.
calc ist nach der Zuweisung von 0 immer noch 5689344

Da brat mir einer einen Storch wenn das kein Bug ist, wenn ich lokalen Variablen keine Werte zuweisen kann, egal ob initialisiert oder nicht.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: simple Wertübergabe funktioniert nicht

Beitrag von Michl »

Versuche doch einfach den Fehler einzugrenzen, wie marcov schon schrieb und/oder lade ein Minimalbsp. ohne Executable hier hoch. Günstig ist es alle Überprüfungen einzuschalten unter Projekt -> Projekteinstellungen -> Debuggen -> Überprüfungen (alle anschalten).
Wir könnten hier sonst nur raten und das wird wahrscheinlich nichts.

PS: Falls es wirklich ein Bug wäre, fände ich es persönlich sehr spannend diesen aufzudecken und auf das Mindeste reduziert im Bugtracker zu melden - nur sie sind "leider" sehr sehr rar geworden :wink: .

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

Michl hat geschrieben:Versuche doch einfach den Fehler einzugrenzen, wie marcov schon schrieb und/oder lade ein Minimalbsp. ohne Executable hier hoch. Günstig ist es alle Überprüfungen einzuschalten unter Projekt -> Projekteinstellungen -> Debuggen -> Überprüfungen (alle anschalten).


Werde ich mal probieren, Danke sehr bis hierher!

TBug
Beiträge: 177
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: simple Wertübergabe funktioniert nicht

Beitrag von TBug »

MickDundee hat geschrieben:

Code: Alles auswählen

 
procedure TmyObj2.calc(myObjnummer:word);
var I_, calc:myrange;
    i,j:word;
begin
    calc:=0;
    ...
 



Das würde bei mir überhaupt nicht kompilieren!

Fehler:
Projekt kompilieren, Ziel: project1.exe: Exit code 1, Fehler: 1, Hinweise: 1
unit1.pas(43,3) Error: Duplicate identifier "Calc"
unit1.pas(43,3) Hint: Identifier already defined in unit1.pas at line 21


Einen Variabelname zu vergeben, welcher gleichzeitig der Name einer Funktion oder Procedur ist, muss schiefgehen.

Benenne die Interne Variable um.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: simple Wertübergabe funktioniert nicht

Beitrag von Michl »

TBug hat geschrieben:Das würde bei mir überhaupt nicht kompilieren!
In {$mode delphi} sind solche versteckten Eier schon erlaubt, ob es schön ist, steht auf einem anderen Blatt...

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: simple Wertübergabe funktioniert nicht

Beitrag von wp_xyz »

[quote="MickDundee"]

Code: Alles auswählen

 
constructor TmyObj2.create;
begin
    inherited;
    anzahl_inputs:=1;
    anzahl_outputs:=0;
    setlength(inputliste,anzahl_inputs);
end;
 

Na dann ist es klar: Du dimensioniert das Array nur für 1 Element (inputliste[0]), greifst aber auf das 2. zu (inputliste[1]). Ein beliebter Fehler, weil die Indexnummerierung bei 0 beginnt. Verwende "anzahl_input := 2", dann sollte es gehen.

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

TBug hat geschrieben:
Fehler:
Projekt kompilieren, Ziel: project1.exe: Exit code 1, Fehler: 1, Hinweise: 1
unit1.pas(43,3) Error: Duplicate identifier "Calc"
unit1.pas(43,3) Hint: Identifier already defined in unit1.pas at line 21


Einen Variabelname zu vergeben, welcher gleichzeitig der Name einer Funktion oder Procedur ist, muss schiefgehen.

Benenne die Interne Variable um.


muahaha, ich Blindfisch
das hab ich noch gar nicht gesehen, oder wie Homer sagt: "Doh' !"
der Wald vor lauter Bäumen...

Danke, danke, danke!

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

wp_xyz hat geschrieben:Na dann ist es klar: Du dimensioniert das Array nur für 1 Element (inputliste[0]), greifst aber auf das 2. zu (inputliste[1]). Ein beliebter Fehler, weil die Indexnummerierung bei 0 beginnt. Verwende "anzahl_input := 2", dann sollte es gehen.


dann frag ich mich aber warum ich inputliste[1].wert:=1 überhaupt ohne Fehler zuweisen kann...

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: simple Wertübergabe funktioniert nicht

Beitrag von Warf »

MickDundee hat geschrieben:
wp_xyz hat geschrieben:Na dann ist es klar: Du dimensioniert das Array nur für 1 Element (inputliste[0]), greifst aber auf das 2. zu (inputliste[1]). Ein beliebter Fehler, weil die Indexnummerierung bei 0 beginnt. Verwende "anzahl_input := 2", dann sollte es gehen.


dann frag ich mich aber warum ich inputliste[1].wert:=1 überhaupt ohne Fehler zuweisen kann...


Na das ist recht simpel, einen Fehler bekommst du nur wenn du versuchst auf unallokierten Speicher zuzugreifen, den Ausdruck inputliste[1].wert:=1 könnte man via Zeiger so ausdrücken: ^MyRange(@inputliste[0] + SizeOf(TIO_put) * 1 + ElementOffset)^ := 1;
Dabei nimmst du lediglich die Adresse des Ersten array elements, addierst das Offset des Index (SizeOf(...)*Index) und dann noch den Offset der einzelnen Record Elemente (also Nummer und name), welches der Compiler vorgibt, da es sich nicht um einen Packed record handelt kann ich die Größe davon nicht genau bestimmen.
Das ist nun ein Zeiger irgendwo auf den Virtuellen Adressraum deines Prozesses. Ist dieser Speicherbereich nun belegt, also bereits an anderer Stelle allokiert worden (z.B. durch new, GetMem, oder Create von Objekten) so wird dir das System keinen Fehler werfen, ist dieser Speicher nicht allokiert, so bekommst du eine Access Violation und dein Programmfluss wird unterbrochen.

Was genau an dieser Stelle im Speicher steht kann ich dir nicht sagen, aber wie es scheint wirst du wohl irgend einen Wert überschrieben haben, dass kann z.B. ein Feld einer anderen Klasse sein, oder aber auch ein anderes Array, oder whatever. An dieser stelle kannst du froh sein dass du deinen Fehler recht schnell bemerkt hast, es kann vorkommen dass du Ewigkeiten nach dem Fehler in Klasse A suchst, der davon hervorgerufen dass irgendwo in Prozedur B zufällig ein Feld von A überschrieben wurde ohne dass B irgend etwas mit A zu tun hat

Ein schönes Beispiel wo das nicht so glimpflich abläuft ist das folgende:

Code: Alles auswählen

procedure Test;
var arr: packed array[0..1] of IntPtr;
begin
  arr[2]:=@Test;
end;

Damit hättest du die Rücksprungadresse überschrieben und wärst in einer Rekrusionsschleife gefangen

Vermeiden kann man dass via Rangechecks im GDB

MickDundee
Beiträge: 9
Registriert: Fr 4. Sep 2015, 14:03

Re: simple Wertübergabe funktioniert nicht

Beitrag von MickDundee »

MickDundee hat geschrieben:
wp_xyz hat geschrieben:Na dann ist es klar: Du dimensioniert das Array nur für 1 Element (inputliste[0]), greifst aber auf das 2. zu (inputliste[1]). Ein beliebter Fehler, weil die Indexnummerierung bei 0 beginnt. Verwende "anzahl_input := 2", dann sollte es gehen.


dann frag ich mich aber warum ich inputliste[1].wert:=1 überhaupt ohne Fehler zuweisen kann...


in diesem Fall lag ich falsch denn ich habe die create-Methode für ein anderes myObjekt hier rein kopiert
die richtige lautet natürlich

Code: Alles auswählen

 
constructor TmyObj.create;
begin
    inherited;
    anzahl_inputs:=2;
    anzahl_outputs:=1;
    setlength(inputliste,anzahl_inputs);
end;
 

Antworten