Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   TObjectList problem... (https://www.delphipraxis.net/156989-tobjectlist-problem.html)

gibb 23. Dez 2010 09:10

TObjectList problem...
 
Hallo zusammen,

Ehrlich gesagt habe ich keine Ahnung was los ist, aber irgendwas ist ganz ganz komisch in meiner App. ^^'

Ich habe folgende zwei Loops implementier (Schon länger her, aber jetzt bereiten sie mir probleme)


nun zum Problem:
Nachdem i im ersten Loop 8 erreicht hat. (von 10) und das end des loopes erreicht resp überschritten wird zerschiesst er mir den inhalt der FVoltOVList (die sich im loop unterhalb befindet.). Das heisst dort steht dann nur noch müll in der Liste und wenn ich anschliessend versuche das Objekt auszulesen bekomm ich ne Access vaiolation.

Das was mir nicht in den Kopf geht ist, das wirklich bis zu dem Zeitpunkt wo das end überschritten wird alles noch in bester Ordnung ist :-/

Ich habe auch die Loops umgedreht. also zuerst die voltOV und erst dann die Fans... das funktioniert dann bis ich das nächste mal auf die FVoltOVList zugreife und mir ein objekt rausholen will.
Code:
  For i:= 0 to FFanOvList.Count -1 do begin
    FanObject:= FFanOvList[i] as TFanOverlayObject;
    FanObject.RPM:= ResultRecord.fans[FanObject.RPMArrayPos];
    FanObject.NewSpeed := GetNewSpeedForAFan(FanObject);
    If FanObject.IdleRPM > FanObject.RPM then
      FanObject.IdleRPM:= FanObject.RPM
    else If FanObject.LoadRPM < FanObject.RPM then
      FanObject.LoadRPM:= FanObject.RPM;
  end;

  for i := 0 to FVoltOvList.Count - 1 do begin
    VoltObject:= FVoltOvList[i] as TVoltOverlayObject ;
    VoltObject.Voltage:= ResultRecord.Volts[VoltObject.VoltArrayPos]/100 ; //FormatFloat('###0.0##',ResultRecord.Volts[VoltObject.VoltArrayPos]/100)
    If VoltObject.IdleVolt > VoltObject.Voltage then
      VoltObject.IdleVolt:= VoltObject.Voltage
    else If VoltObject.LoadVolt < VoltObject.Voltage then
      VoltObject.LoadVolt:= VoltObject.Voltage;
  end;
hat jemand eine idee woran das liegen könnte?

Gruss Sev

Bummi 23. Dez 2010 09:30

AW: TObjectList problem...
 
wie spielt ResultRecord da mit?

gibb 23. Dez 2010 09:41

AW: TObjectList problem...
 
Das ist folgender record
Code:
  TResultIntRecord = Packed Record
    Unknown : Array[0..5] of SmallInt;//unbekanntes Tag
    NumTemps : SmallInt; //Anzahl der Temperaturen
    NumFans : SmallInt; //Anzahl der Lüfter
    NumVolts : SmallInt; //Anzahl der Spannungen
    Temps   : Array[0..63] of smallint; //Werte der Temperaturen
    Fans    : Array[0..63] of smallint; //Drehzahl der Lüfter
    Volts   : Array[0..63] of smallint; //Werte der Spannungen
  end;
er beinhaltet die Daten die ich auslese das auslesen passiert hier:

Code:
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: TResultIntRecord;
begin
  result:= False;
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      //CopyMemory nicht machen wenn im debug modus
      CopyMemory(Addr(FintData),SfAreaPtr,sizeof(MyResultRecord));

      if (FIntData.NumFans=0) and (FIntData.NumTemps=0) and (FIntData.NumVolts=0) then begin
        if FTryesToStartSpeedfan <= 240 then begin
          inc(FTryesToStartSpeedfan);
          application.ProcessMessages;
          Sleep(1000);
          ReadSFData ;
        end else begin
          MessageBox(application.Handle,'No Fan Sensores from Speedfan Found. Shuting down the application ','Failure',MB_OK);
          Application.Terminate;
        end;
      end;
      Result:= True;
    end;
  finally
    If not result then begin
      if Fileexists(GPConfiguration.GetValue('SpeedFanExePath','asd')) then begin
        if not processExists(ExtractFileName(GPConfiguration.GetValue('SpeedFanExePath','asd'))) then
          ShellExecute(Application.Handle,'open',PChar(ExtractFileName(GPConfiguration.GetValue('SpeedFanExePath',''))),'',PChar(ExtractFilePath(GPConfiguration.GetValue('SpeedFanExePath',''))),SW_SHOW);
        while FTryesToStartSpeedfan <= 120  do begin
          if OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM')<> 0 then
            FTryesToStartSpeedfan:=120 ;
          Sleep(1000);
          Application.ProcessMessages;
          inc(FTryesToStartSpeedfan);
        end;
        hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
        if HsfMemory = 0 then begin
          MessageBox(application.Handle,'Failed to Start and Read SpeedFan Data. Make shure that SpeedfanExePath is right in the configuration.','Failure',MB_OK);
          Application.Terminate;
        end else begin
          ReadSFData;
          FTryesToStartSpeedfan:=0;
        end;
      end;
    end;
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
Der wird vor den 2 loops aufgerufen.

Code:
  Result:= GPReadSpeedFan.ReadSFData;
  ResultRecord:= GPReadSpeedFan.GetResultRecord;

taveuni 23. Dez 2010 10:16

AW: TObjectList problem...
 
Zitat:

Zitat von gibb (Beitrag 1070110)
Code:
  For i:= 0 to FFanOvList.Count -1 do begin
    FanObject:= FFanOvList[i] as TFanOverlayObject;
...
hat jemand eine idee woran das liegen könnte?
Gruss Sev

ist das nicht eher

Delphi-Quellcode:
FanObject:= FFanOvList[i].Items as TFanOverlayObject;
?

gibb 23. Dez 2010 10:23

AW: TObjectList problem...
 
wie kommst du darauf? Wenn ich das machen würde würde dies dasselbe machen wie TFanOverlayObject.items und das biete ich nicht an. Das was du wohl meinst ist FFanOvList.items[i] aber ich weiss gerade nicht ob die TObjectlist das anbietet. und wenn ja währe meine lösung dasselbe aus meiner sicht.

Bummi 23. Dez 2010 10:30

AW: TObjectList problem...
 
Mit dem Debugger bist Du bestimmt schon drübergegangen, ich vermute der Fehler kommt irgendwo außerhalb Deiner Schleifen zustande.

gibb 23. Dez 2010 10:48

AW: TObjectList problem...
 
das vermute ich auch aber ich weiss nicht wo suchen. Ich versuche es noch einmal zu erklären

Ich hab mir ne Watch gemacht auf TVoltOverlayObject(FVoltOVList[1]) diese Watch habe ich beobachtet beim Debuggen. diese watch ist okey bis zum step ( 1. zu 2. komentare) und das wenn i = 8 ist.

Also in dem moment wo er einen durchlauf beendet hat und wieder hochspringt zur bedingung gehen meine Objekte flöten. wieso auch immer und ich wüsste nicht was mir da genau einen strich durch die rechnung macht.

Hast du eine ahnung was in dieser zeit noch passiert?


Delphi-Quellcode:
var
  TempObject: TTempOverlayObject;
  FanObject: TFanOverlayObject;
  VoltObject: TVoltOverlayObject;
  i: Integer;
  ResultRecord: TResultIntRecord;
  MyTobject: TObject;
begin

  Result:= GPReadSpeedFan.ReadSFData;
  ResultRecord:= GPReadSpeedFan.GetResultRecord;
  For i:= 0 to FTempOvList.Count -1 do begin
    TempObject:= FTempOvList[i] as TTempOverlayObject;
    TempObject.Temp:= ResultRecord.Temps[TempObject.TempArrayPos] div 100;
    If TempObject.IdleTemp > TempObject.Temp then
      TempObject.IdleTemp:= TempObject.Temp
    else If TempObject.LoadTemp < TempObject.Temp then
      TempObject.LoadTemp:= TempObject.Temp;
  end;

  For i:= 0 to FFanOvList.Count -1 do begin// <---------2. objekte sind flöten und i = 9
    FanObject:= FFanOvList[i] as TFanOverlayObject;
    FanObject.RPM:= ResultRecord.fans[FanObject.RPMArrayPos];
    FanObject.NewSpeed := GetNewSpeedForAFan(FanObject);
    If FanObject.IdleRPM > FanObject.RPM then
      FanObject.IdleRPM:= FanObject.RPM
    else If FanObject.LoadRPM < FanObject.RPM then
      FanObject.LoadRPM:= FanObject.RPM;
  end; // <------------ 1. hier stand i= 8 und meine objekte in der liste weiter unten sind noch richtig. anschliessend wieder einen step im debuger

  for i := 0 to FVoltOvList.Count - 1 do begin
    MyTobject:= FVoltOVList[i];
    if FVoltOvList[i] is TVoltOverlayObject then
      VoltObject:= FVoltOvList[i] as TVoltOverlayObject ;
    VoltObject.Voltage:= ResultRecord.Volts[VoltObject.VoltArrayPos]/100 ; //FormatFloat('###0.0##',ResultRecord.Volts[VoltObject.VoltArrayPos]/100)
    If VoltObject.IdleVolt > VoltObject.Voltage then
      VoltObject.IdleVolt:= VoltObject.Voltage
    else If VoltObject.LoadVolt < VoltObject.Voltage then
      VoltObject.LoadVolt:= VoltObject.Voltage;
  end;

Bummi 23. Dez 2010 11:01

AW: TObjectList problem...
 
Kann es sein daß Dir beim lesen von ResultRecord der Stack kaputtgeschrieben wird?
Pack ResultRecord: TResultIntRecord; mal testweise in eine globale Variable.

gibb 23. Dez 2010 11:11

AW: TObjectList problem...
 
was sollte dann passieren?

also funzen tuts nicht wenn ich das mache.... was aber ist das problem tritt nicht immer von 8-9 auf kann auch von 3-4 oder von 4-5 oder garnicht O.ô hatte vorhin einen fall da hat alles sauber funktioniert... für 2 mal und dann wieder kapput.

Bummi 23. Dez 2010 11:24

AW: TObjectList problem...
 
Da ich einen Stackfehler vermute würde ich zu Eingrenzungszwecken, den kompletten Var-Teil bis auf i in einen globalen Speicherbereich umziehen, aber wirklich helfen kann ich Dir von hier aus nicht ...

gibb 23. Dez 2010 11:33

AW: TObjectList problem...
 
ich könnte dir theoretisch auch das Projekt zusenden. Aber sei gewarnt erst war nur was kleines angedacht und es ist dann gewachsen. Ich bin gerade am refactoring um einige desing patterns einzuführen.

Ich versteh leider sehr sehr wenig von Stackfehler um nicht zu sagen garnichts. Ich habe auch keine erfahrungen darin wie man diese eingrenzen kann und ich versteh ehrlich gesagt auch nicht was es hilft die variablen in einen globalen speicherbereich zu zügeln.

Also was mir helfen würde:
1. Du erklärst mir genauer wie ich das debuggen/eingrenzen kann.
2. Oder ich sende dir den code zu...

mit globalen speicherbereich meinst du was? Eine objektvariable daraus zu machen oder gar klassenvariable. ?

stahli 23. Dez 2010 12:02

AW: TObjectList problem...
 
Hast Du vielleicht Deine Arraygrößen verändert und die Bereichsprüfung nicht aktiviert?
Beim Schreiben über Arraygrenzen hatte ich ähnliche Effekte auch schon zu beklagen :stupid:

Bummi 23. Dez 2010 14:24

AW: TObjectList problem...
 
Ich hatte ganz einfache globale Variablen gemeint, am besten getrennt durch leere Arrayvariablen, deren Inhalt man beim Debuggen miteinsehen kann um zu schauen wann das etwas überläuft.
Man könnte auch alle beteiligten Funktionen und Prozeduren auf Korrektheit prüfen.
Wenn's nicht eilig ist und ich keine Komponenten installieren musst kannst mir den Code gerne schicken, besser wird es sein ihn ins Forum zu stellen, was der eine übersieht findet ein anderer.

gibb 24. Dez 2010 08:24

AW: TObjectList problem...
 
Hallo zusammen, ich prüffe jetzt noch das Array.

Den kompletten code ins forum zu stellen ist wohl eher schwierig. Es sind immerhin 9 Units und 4 forms. Aber es eilt nicht... ist ein "privates" projekt....


gruss Sev

gibb 24. Dez 2010 08:38

AW: TObjectList problem...
 
Also, ich habe die arrays geprüfft da wird nirgendwo über die array grösse hinaus gelesen. das mit den Globalen Variablen bringt auch keinen Erfolg :-/

gruss Sev

gibb 24. Dez 2010 09:53

AW: TObjectList problem...
 
hab die zeile gefunden:

Delphi-Quellcode:
function TSensorFactory.GetNewSpeedForAFan(AFan: TFanOverlayObject):Integer;
var
  i: Integer;
  TempSens, MasterTemp: TTempOverlayObject;
  NewSpeed, currentspeed: Integer;
  HighestSpeed: Integer;
begin
  Result:= -1;
  HighestSpeed:= -1;
  Currentspeed:= AFan.NewSpeed;
  if AFan.Enabled then begin
    // Alle sensoren werden durchgesteppt
    for i:= 0 to FTempOvList.Count-1 do begin
      TempSens:= FTempOvList[i] as TTempOverlayObject ;
      //Wenn der Sensor aktiv ist wird geschaut ob dieser Fan überhaupt für diesen sonsor verantwortlich ist
      If TempSens.Enabled then begin
        NewSpeed:= CalculateNewSpeed(Tempsens, Afan);
        if newSpeed > HighestSpeed then begin
          HighestSpeed:= NewSpeed;
          MasterTemp:= TempSens;
        end;
      end;
    end;
      //über oder unter der hysterese else in der hysterese
    if (MasterTemp.Temp >= (MasterTemp.OldTemp + MasterTemp.Offset) ) or
       (MasterTemp.Temp <= (MasterTemp.OldTemp - MasterTemp.Offset)) or
       (HighestSpeed = 100) then begin
     // MasterTemp.OldTemp:= MasterTemp.Temp; <--- wennn ich diese zeile auskomentiere dann geht es :-/
      Result:= HighestSpeed;
    end else
      Result:= currentspeed;
ich versteh nur nicht was ihn daran stört :-/

edit:

Noch die Passende klasse dazu:
Delphi-Quellcode:
  TTempOverlayObject = Class(Tobject)
  public
    TempArrayPos: Integer; //Position im Rückgabearray
    RealName : String;    //Namen im System
    overlayName: String;  //Anzeigenamen
    LowestTemp: integer; //Konfigurierte min Temp
    HighestTemp: integer; //Konfigurierte höchsttemperatur
    Temp: Integer; //Aktuelle Temperatur
    OldTemp:Integer; //Letzte Temperatur vor der Temp änderung (für hysterese wichtig)
    Offset: integer; //Offset für die Hysterese
    Enabled: Boolean; //Aktiv/Inaktiv
    IdleTemp: Integer;
    LoadTemp: Integer;
    ResponsibleFans: TObjectlist; // Fans die Zuständig sind für diesen Sensor.
    constructor create;
    destructor destroy(); override;
  End;

DelphiBandit 24. Dez 2010 10:14

AW: TObjectList problem...
 
Passt zwar nicht zu der von Dir auskommentieren Zeile und ist ohne Debugger nur aus dem Bauch heraus. Was passiert denn, wenn MasterTemp in der oberen Schleife überhaupt nicht zugewiesen wird. Dann kracht es im unteren Bereich, allerdings imho schon in der If-Abfrage.

Initialisiere MasterTemp über der for-Schleife mal mit nil und prüfe als erste Bedingung unten, ob es im for überhaupt zugewiesen wurde (if assigned).

stahli 24. Dez 2010 10:17

AW: TObjectList problem...
 
Ist MasterTemp vielleicht undefiniert? Dann schreibst Du ja in irgend einen Speicherbereich.
Setze MasterTemp vor Deiner Schleife mal auf nil und teste bei der späteren Behandlung auf <> nil.

gibb 24. Dez 2010 10:18

AW: TObjectList problem...
 
hab die lösung -.-

if(Assigned(MasterTemp)) and( (MasterTemp.Temp >= (MasterTemp.OldTemp + MasterTemp.Offset) ) or
(MasterTemp.Temp <= (MasterTemp.OldTemp - MasterTemp.Offset)) or
(HighestSpeed = 100)) then begin

DelphiBandit 24. Dez 2010 10:20

AW: TObjectList problem...
 
:D - nu ja, da haben wir am Ende ja gleich eine gleiche "Dreifach-Lösung" innerhalb von 4 Minuten.

Die Zuweisung auf nil vorher solltest Du auf jeden Fall auch noch ergänzen!

gibb 24. Dez 2010 10:20

AW: TObjectList problem...
 
haha

schön das ich nicht der einzige bin ders jetzt auch gesehen hat -.-'

Idiotisch ^^'

geknallt hats aber nirgends sondern es hat mir meine andere liste zerschossen. Idiotisch.

aber danke für die bemühungen...

stahli 24. Dez 2010 10:21

AW: TObjectList problem...
 
Dann kann er nach Weihnachten 2 davon umtauschen :-D

gibb 24. Dez 2010 10:31

AW: TObjectList problem...
 
:lol: ja das nil ist mit meiner lösung bereits implementiert.... sonst würde er bei assigned durchlaufen weil dort war irgendwas assigned nur nicht das was ich gerne gehabt hätte..

gemerkt hab ichs nur weil ich mir den wert von i weggespeichert hab und dann versucht habe mit diesem wert die liste auszulesen. und da hats geknallt weil i nicht initialisiert war ^^'


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz