Autor Beitrag
passiv
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Mi 05.03.08 13:35 
Hallo Forum

Mein Problem besteht heute aus der Kombination DLL und PChar.

Und zwar hab ich einen eigenen "Typ" erstellt
ausblenden Delphi-Quelltext
1:
2:
3:
4:
  Sarry=^TSarry;
  TSarry=record
    Cells: array [0..6,0..60] of pchar;
    end;

und meine Variable, in die ich meine Werte reinlade, ist eben vom Typ Sarry

Sarry sieht im Host-Programm und in der DLL gleich aus (sonst ginge es ja nicht)

Ich hab zur Zeit 2 Prozeduren in Angriff genommen:
Die 1. erstellt eine Überschrift, die Variable, in der das transportiert wird, ist auch vom Typ Sarry. Diese funktioniert einwandfrei (ich lass mir das im Programm in ein Stringgrid ausgeben)
Die 2. erstellt eine Tabelle in Form von Berechnungen. Auch in die gleiche Variable, Typ Sarry. Zu stinken fängt es an, wenn ich eine Schleife (for Laufvariable:=1 to 60 do) benutze, die mir SG.Cells[0,Laufvariable] mit PChar(inttostr(Laufvariable)) füllt. Juhuu, soweit so schön. Das gibt aber das Problem, dass er mir die Zellen abwechselnd mit 60 und 63 füllt (Bild im Anhang) ...

Dann berechne ich für die 1. Zeile im Array (um die Beschriftung links nicht zu stören, nur von 1 bis 6) diverse Startwerte. Aus diesen Startwerten kann ich für die darauffolgenden Spaltenwerte auch noch was ausrechnen. Diese Rechnung funktioniert gut, ich hab sie schon ausserhalb der DLL getestet.
Den Rest der Tabelle füllt er, anstatt mit "wissenschaftlichen" Rechnungen, einfach nur mit absolutem Müll (Bild 2 im Anhang) ...

Ich bin total verzweifelt, weil mir mein Lehrer auch nicht mehr helfen kann (naja, den interessieren DLL's zu wenig), das aber mein Matura-Projekt werden sollte ...

mfG und danke für die Hilfe im Vorraus

passiv
Einloggen, um Attachments anzusehen!
_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Mi 05.03.08 18:07 
Hi,

Also wenn ich nichts verpasst habe bedeutet das "P" doch immer, dass es sich um einen Zeiger handelt.
Warum denn Zeiger?
Habe ich etwas übersehen?

Edit: Wenn die Zeiger auf den Falschen Speicher zugreifen würden bekäme man doch den von dir beobachteten Datenmüll...


mfG,

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 05.03.08 18:26 
Das Problem dürfte sein, dass du den Speicher für die PChars nicht im Hauptprogramm reserviert hast. Die PChar-Pointer an sich sind dann zwar vorhanden, der Speicher für die PChars wird aber bei der Zuweisung in der DLL erst in Beschlag genommen. Und auf den kannst du dann ja im Hauptprogramm nicht mehr zugreifen, wenn die Funktion zurückgekehrt ist.

Deshalb vermute ich, dass es geht, wenn du mit GetMem den Speicher für die einzelnen PChars erst holst, das gehen müsste. Der muss dann natürlich ggf. auch mit FreeMem wieder freigegeben werden.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Do 06.03.08 11:01 
user profile iconHidden hat folgendes geschrieben:
Hi,
Edit: Wenn die Zeiger auf den Falschen Speicher zugreifen würden bekäme man doch den von dir beobachteten Datenmüll...

tja, und das skurrile an der Geschichte ist, dass ich in der Funktion HeadLine noch richtige Werte bekomme ... sonst würd ich den ganzen Krempel einfach mit GetMem und FreeMem abschreiben, aber das hat mich stutzig und neugierig gemacht, was da falsch ist (Grundlagenforschung^^)

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Do 06.03.08 12:34 
Das Problem hat nichts mit der DLL zu tun sondern lediglich mit der Gültigkeit von Delphistrings.
ausblenden Delphi-Quelltext
1:
PChar(inttostr(Laufvariable))					


IntToStr erzeugt einen String. Von diesem Merkst du dir den Pointer. Aber Strings haben eine Referenzzählung genau diese hebelst du mit pChar() aus. Denn am Ende der Methode werden die Strings gelöscht auf die niemand referenziert. Innerhalb der Methode sind sie aber noch gültig. Selbst, wenn du andere Methoden aufrufst. Aber danach können sie jederzeit überschrieben werden. Die Zuweisung eines pChars auf ein StringGrid sorgt dafür, dass ein DelphiString erstellt wird. Sozusagen eine Kopie. Weswegen das funktioniert.

Entweder du erstellst einen eigenen Speicher mit GetMem etc oder aber du erstellst mittel StrNew eine Kopie des pChars. Diesen musst du aber wieder freigeben ansonsten entsteht ein Speicherloch. Und das wirst du dann aber wieder in der DLL machen müssen, denn sonst bekommt der Speichermanager deiner Anwendung einen Schock.

Oder aber ganz anderst. Du konvertierst diese Sachen einfach nicht und reichst stumpf die Werte weiter. Natürlich nur, wenn das möglich ist. Denn dann muss sich jeder selber darum kümmern was mit den Werten passiert. Also dann als String konvertieren etc. Zu mal du auch nicht so eingeschränkt bist was dein weiteres Handeln angeht.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Do 06.03.08 13:18 
@user profile iconLossy eX: wow, das war verständlich. Danke!

user profile iconLossy eX hat folgendes geschrieben:
Oder aber ganz anderst. Du konvertierst diese Sachen einfach nicht und reichst stumpf die Werte weiter. Natürlich nur, wenn das möglich ist. Denn dann muss sich jeder selber darum kümmern was mit den Werten passiert. Also dann als String konvertieren etc. Zu mal du auch nicht so eingeschränkt bist was dein weiteres Handeln angeht.

naja das hatte ich mir auch überlegt, bin aber davon abgekommen, als ich bemerkt habe, dass ich bei 2 oder 3 Tabellen dann wieder Beschriftungen innerhalb der Tabelle brauche, aber eben mit inttostr mit einer Wertangabe (im konkreten Fall einfach € hintendran). Das ist aber eben abhängig von den Werten, die in der DLL ausgerechnet werden ... Und ich bin wegen "Updatebarkeit" auf DLL's umgestiegen, um nicht immer die gesamte EXE herunterladen zu müssen, nur weil sich im Algorythmus (pro Bundesland verschieden (Österreich), Änderungen wurden schon wieder angekündigt) was ändert.

Sämtliche Alternativen sind nur mit Delphi Nutzbar und weil es mein Matura-Projekt wird, ist es auch mein Wunsch was neues zu machen, was sich eben in DLL's ausschlagen würde.

Und das ist jetzt aktuell auch meine Zwickmühle ...

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Do 06.03.08 14:02 
Na ja. Also unmöglich ist das jetzt auch nicht. Da du die Werte nicht direkt übergeben kannst musst du halt nen nullterminierten String benutzen. Ich habe eine Bibliothek gebaut (bin noch dabei aber schon ziemlich weit) die sehr viel mit Texten rumhantiert. Du musst nur dafür sorgen, dass erstellte Texte wieder frei gegeben werden. Dazu ein kleiner Vorschlag von mir.

Deine DLL würde folgende Methoden Exportieren.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
CreateSarry: PSarry; stdcall;
DestroySarry (Sarry: PSarry); stdcall;

CalcSarry (Sarry: PSarry); stdcall;  // Oder so was

CreateSarry würde eine Struktur von PSarry über GetMem erzeugen und mit 0 füllen.
DestroySarry würde die Struktur wieder löschen und evtl. vorhandene nullterminierte Strings auch gleich mit.

CalcSarry ist nur ein Beispiel aber da würde dann die Anwendung einen Speicherbereich an die DLL übergeben der auch von der DLL erzeugt wurde. Dort würdest du dann via StrNew die pChars ablegen und evtl vorhandene vorher wieder löschen.

Um dafür zu sorgen, dass die Anwendung nicht wissen muss wie die Struktur aufgebaut sein muss (habe gerade so einen Fall wo ich am liebsten die Lib gegen die Wand klatschen würde), solltest du Methoden zum Zugriff bereit stellen. Also so etwas GetWidth, GetHeight, GetCell. Die jeweils immer das PSarry übergeben bekommen und entweder Breite, Höhe oder einen pChar zurück liefern. Das aber nur, wenn es wirlich Sprachunabhängig sein sollte.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Do 06.03.08 15:02 
user profile iconLossy eX hat folgendes geschrieben:
DestroySarry würde die Struktur wieder löschen und evtl. vorhandene nullterminierte Strings auch gleich mit.
Würde das
ausblenden Delphi-Quelltext
1:
FreeMem(SarryVariable)					

oder
ausblenden Delphi-Quelltext
1:
2:
for x:=0 to 6 do
  for y:=0 to 60 do FreeMem(SarryVariable.Cells[x,y]);
heißen? Ich hab GetMem und FreeMem noch nie verwendet und die Delphi-Hilfe liefert eher technische Details zum Ablauf, nicht aber zur Verwendung von Arrays (geschweige denn Sarrys :roll: )

user profile iconLossy eX hat folgendes geschrieben:
CalcSarry ist nur ein Beispiel aber da würde dann die Anwendung einen Speicherbereich an die DLL übergeben der auch von der DLL erzeugt wurde. Dort würdest du dann via StrNew die pChars ablegen und evtl vorhandene vorher wieder löschen.
Und hier ginge das meinem Verständnis nach mit der Wertübergabe aus Integer auf PChar dann so:
ausblenden Delphi-Quelltext
1:
SarryVariable.Cells[x,y]:=StrNew(PChar(inttostr(IntegerVariable)));					

user profile iconLossy eX hat folgendes geschrieben:
Um dafür zu sorgen, dass die Anwendung nicht wissen muss wie die Struktur aufgebaut sein muss (habe gerade so einen Fall wo ich am liebsten die Lib gegen die Wand klatschen würde), solltest du Methoden zum Zugriff bereit stellen. Also so etwas GetWidth, GetHeight, GetCell. Die jeweils immer das PSarry übergeben bekommen und entweder Breite, Höhe oder einen pChar zurück liefern. Das aber nur, wenn es wirlich Sprachunabhängig sein sollte.
Gut, das lass ich dann eben noch weg :lol: .

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Do 06.03.08 16:04 
Zitat:
Gut, das lass ich dann eben noch weg :lol: .

Genau. Da du es warscheinlich sowieso selber machen wirst muss man es nicht übertreiben.

ausblenden Delphi-Quelltext
1:
SarryVariable.Cells[x,y] := StrNew(PChar(inttostr(IntegerVariable)));					

Ja so in etwas denke ich mir das. Der Übersicht halber und für Debuggzwecke kann man das noch in 2 Zeilen inklusive temporärer Stringvariable packen. Aber so sollte es auch problemlos gehen.

Da ich sehe, dass du noch ein kleines Defizit hast was Pointer angeht nehme ich das Erstellen noch mit rein.
Records erstelle ich persönlich eher mit New. Ist aber genau das gleiche wie GetMem nur, dass New selber die Größe bestimmt und man bei GetMem expliziet eine Größe angeben muss. Alternativ kannst du auch AllocMem benutzen. Das erstellt den Speicher auch nur mittels GetMem aber füllt ihn gleich mit FillChar. Wie man es macht ist Geschmackssache. Im Ergebniss ist es immer wieder das Gleiche. ;) StrNew und StrDispose arbeiten intern auch nur mit GetMem und FreeMem.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
CreateSarry: PSarry;
begin
  New(Result); // Speicher reservieren und Pointer in Result speichern
  FillChar(Result^, SizeOf(TSarry), 0);  // Speicher löschen
end

DestroySarry(Sarry: PSarry);
begin
  for Y := 0 to max do
    for X := 0 to max do
      if Sarry^.Cell[Y, X] <> nil then
        StrDispose(Sarry^.Cell[Y, X]);  // Strings löschen

  Dispose(Sarry);  // Hauptstruktur löschen.
end

CalcSarry(Sarry: PSarry);
var
  TempStr: String;
begin
  TempStr := IntToStr(...);
  Sarry^.Cell[Y, X] := StrNew(pChar(TempStr));
end


PS: Falls du später mit dynamischen Arrays arbeiten willst musst du aufpassen. Denn dynamische Arrays sind intern auch nur Pointer.

PPS: Falls du generelle Verständnissprobleme mit Pointern hast solltest du dir wohl besser ein Grundlagentutorial aneignen. Da ist das sicher verständlicher geschrieben. ;)

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Fr 07.03.08 11:21 
user profile iconLossy eX hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
DestroySarry(Sarry: PSarry);
begin
  for Y := 0 to max do
    for X := 0 to max do
      if Sarry^.Cell[Y, X] <> nil then
        StrDispose(Sarry^.Cell[Y, X]);  // Strings löschen

  Dispose(Sarry);  // Hauptstruktur löschen.
end
Was würde passieren, wenn ich nur die Hauptstruktur löschen würde?
Würden die 7*61 PChar-Blöcke im RAM verschimmeln, weil sie keiner freigibt?

user profile iconLossy eX hat folgendes geschrieben:
PPS: Falls du generelle Verständnissprobleme mit Pointern hast solltest du dir wohl besser ein Grundlagentutorial aneignen. Da ist das sicher verständlicher geschrieben. ;)
Nö, die hab ich soweit eh schon gecheckt. Es ist eben nur das Ganze in Records und dann noch dazu in den völlig neuen DLL's ...

Aber trotzdem schon mal vielen Dank user profile iconLossy eX für Deine Hilfe und Geduld!

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Fr 07.03.08 13:04 
Zitat:
Würden die 7*61 PChar-Blöcke im RAM verschimmeln, weil sie keiner freigibt?

Genau. Wenn das niemand wieder frei gibt bleiben sie erhalten.

PS: Nichts zu danken. Dafür ist ein Forum ja da. ;)

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Fr 07.03.08 13:50 
Also gut. Das funktioniert soweit ganz schön, die Prozedur füllt meine Tabelle mit Zahlen (die auch stimmen).
Nur gibt er mir schon beim ersten Durchlauf der Prozedur eine Exception
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure DestroySarry(Sarry: PSarry);
var x,y:Integer;
begin
  for Y := 0 to 6 do
    for X := 0 to 60 do
      if Sarry^.Cells[Y, X] <> nil then
        StrDispose(Sarry^.Cells[Y, X]);  // Hier der Fehler
  Dispose(Sarry);  // Hauptstruktur löschen.
end;
Exception hat folgendes geschrieben:
---------------------------
Passivhaus
---------------------------
Access violation at address 004047C7 in module 'Passivhaus.exe'. Read of address 0000000E.
---------------------------
OK
---------------------------
Naja, und weil ich schon so eher nicht verstehe, wann man jetzt eigentlich einen Hut (^) setzen muss, geschweige denn, was er bewirkt (WEIL UNSER SEHR GEEHRTER HERR PROFESSOR DAS EINFACH NICHT WEISS, WEIL ES IHN NICHT INTERESSIERT, ES UNS ABER TROTZDEM BEIBRINGT ...), steh ich gerade ein wenig auf dem Eis.

Achja, weil ich gerade meine RAM zupulvere: kann ich mit diversen RAM-Säuberungs-Tools diese schimmelnden Arrays wieder rausschmeißen?

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Fr 07.03.08 15:57 
Zitat:
Achja, weil ich gerade meine RAM zupulvere: kann ich mit diversen RAM-Säuberungs-Tools diese schimmelnden Arrays wieder rausschmeißen?

Das Beste RAM Säubertool ist Windows. Sobald du deine Anwendung schließt wird alles Speicher der Anwendung von Windows (NT. Bei 98 ist das glaube ich anders) selber gekillt.

Die anderen Tools sind Quatsch. Das Einzige was die machen ist dafür zu sorgen, dass aller Speicher in den virtuellen Speicher (Festplatte) ausgelagert wird. Wenn man jetzt wieder Speicher benötigt, dann wird der wieder in den RAM gelegt. Somit würde unbenutzer Speicher von dauerhaft laufenden Anwendungen in den virtuellen Speicher verschoben. Wenn man das übertreibt erreicht man eher auch einen Bremsenden Effekt. Aber die Tools selber können nichts frei geben. Woher sollen sie auch wissen was.

^: Das ist zum Dereferenzieren von Pointern. Sprich wenn du auf die Daten zugreifen möchtest auf die ein Pointer zeigt. Delphi macht das zwar teilweise alleine aber ich habe mir angewöhnt es grundsätzlich immer zu machen, wenn ich auf die Daten zugreifen will. Ohne ^ und ohne Zugriff auf Recordfelder ist eigentlich immer die Adresse des Pointers gemeint. Aber das meinte ich zum Beispiel mit Grundlagen. ;)

Zugriffsverletzung: Muss ich so passen. Die Adresse 0000000E sieht zu mindest sehr seltsam. Schau mal im Debugger ob die Struktur richtig initialsiert (FillChar) wird. Ansonsten kann ich mit dem bisschen Code nichts anfangen.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Mi 12.03.08 13:46 
Hallo!

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
function CreateSarry: PSarry;
begin
  new(result);  // Speicher reservieren und Pointer in Result speichern
  FillChar(Result^, SizeOf(TSarry), 0);  // Speicher löschen
end;
Hier ist mal die Funktion, die das PSarry erstellt. Die kommt genau so von Dir. Und ich stell mir gerade die Frage, was dagegen spricht es so zu machen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure CreateSarry(Sarry: PSarry);
begin
  new(Sarry);
  FillChar(Sarry^, SizeOf(TSarry), 0);
end;
Dann würde zumindest sicherlich der richtige Speicherplatz reserviert, oder?

Das Stringgrid füllt er mir zwar mit Werten, die aber komplett ungleichmäßig verschoben sind (die erste Zeile fehlt, manche Zellen gegen Ende der Tabelle haben einfach nichts drinstehen, ... siehe Anhang) ...

Achja: Breakpoints in der oben zitierten Funktion zeigen keinerlei aufschlussreiche Ergebnisse ...
Achja2: Seit ich es so (Funktion) mache, spinnt die Überschrift, die ich in einer eigenen Prozedur mache und die bisher (als einziges) einwandfrei funktioniert hat.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function HeadLine:PSarry;
begin
        ClearSG;
        SG.Cells[1,0]:=StrNew(' > 50');
        SG.Cells[2,0]:=StrNew(' 50-41');
        SG.Cells[3,0]:=StrNew(' 40-31');
        SG.Cells[4,0]:=StrNew(' 30-21');
        SG.Cells[5,0]:=StrNew(' 20-16');
        SG.Cells[6,0]:=StrNew(' < 15');
        result:=SG;
end;
Auch ohne SG.Cells[x,0]:=StrNew('irgendwas') gehts nicht. Im pausierten QuellCode zeigt er mir zwar die ganzen Werte an, in das StringGrid schreibt er aber nichts rein.

Ich schick hier mal mit auch einmal die richtige Tabelle und die falsche.

(Die Dateien sind eigentlich .csv-Dateien, die blockt das Forum aber.)
Einloggen, um Attachments anzusehen!
_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Mi 12.03.08 15:49 
Die Methode mit den Parametern funktioniert so nicht. Denn Parameter ohne var oder const werden kopiert auf dem Stack übergeben. Das New(Blah) erzeugt aber einen Speicherbereich und schreibt die Addresse in Blah. Blah ist so aber nur eine Kopie deiner eigentlichen Variable. Somit wird die Adresse wohin geschrieben wo sie nicht benutzt wird. Wenn der Parameter ein var wäre, dann würde intern die Adresse der echten Variable übergeben und jede Änderung davon würde auch in die Variable gelangen.

Wenn der Parameter ein Var wäre, dann wäre es Geschmackssache was man lieber mag. Denn dann wäre das Ergebniss ziemlich gleich nur der Weg etwas anders.

Zu dem Rest: Tut mir leid aber mit den CSV Dateien kann ich gar nichts anfangen. Und mich würde da eher Code außen rum interessieren. Denn das was du da an Code gepostet hast ist unkritisch. Bzw. was macht ClearSG überhaupt? Oder was machst du sonst noch mit den Pointer? Um es mal in meiner Allseits beliebten Bildsprache näher zu bringen. Ich kann dir nicht sagen was an einem Auto kaputt ist, wenn ich nur einen Reifen davon sehe. ;)

Wenn du debuggst, dann solltest du versuchen dir den Weg der Daten anzuschauen. Und wenn du merkst, dass sie irgendwann anders sind, dann solltest du die zwischenschritte genauer anschauen etc.

PS: Außerdem würde ich dir empfehlen bei Pointer immer zu dereferenzieren (mit ^). Ich habe schon mal ein paar seltsame Effekte erlebt, wenn man sich darauf verlässt, dass Delphi das immer so hinbekommt.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Do 13.03.08 11:50 
user profile iconLossy eX hat folgendes geschrieben:
Wenn der Parameter ein var wäre, dann würde intern die Adresse der echten Variable übergeben und jede Änderung davon würde auch in die Variable gelangen.
Aber ja, so meinte ich es doch ^^.

user profile iconLossy eX hat folgendes geschrieben:
Und mich würde da eher Code außen rum interessieren. Denn das was du da an Code gepostet hast ist unkritisch. Bzw. was macht ClearSG überhaupt?
Hier comes the code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure ClearSG;// steht in der DLL drin
var     x,y:Integer;
begin
        for x:=0 to 6 do
                for y:=0 to 60 do SG.Cells[x,y]:=StrNew('');  //auch hier gilt: StrNew zeigt keinen Effekt
end;
Das ist die ClearSG (das sollte man ja eh sehen können :roll: )

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function Heizkost:PSarry;// steht in der DLL drin
var     x,y:integer;
begin
        ClearSG;  //Das mach ich konsequent immer, weil die Variable SG in der DLL global verwendet wird und sonst noch doofe Werte drinstehen, die stören könnten
        SG.Cells[0,0]:='Monatsrate pro Jahr';
        for y:=1 to 60 do SG.Cells[0,y]:=StrNew(PChar(inttostr(y)));
        SG.Cells[1,1]:=StrNew(PChar(floattostr(oroundto(btve*bgf*enp/1200,-2))));
        SG.Cells[2,1]:=StrNew(PChar(floattostr(oroundto(50*bgf*enp/1200,-2))));
        SG.Cells[3,1]:=StrNew(PChar(floattostr(oroundto(40*bgf*enp/1200,-2))));
        SG.Cells[4,1]:=StrNew(PChar(floattostr(oroundto(30*bgf*enp/1200,-2))));
        SG.Cells[5,1]:=StrNew(PChar(fp/1200,-2))));
        SG.Cells[6,1]:=StrNew(PChar(floattostr(oroundto(15*bgf*enp/1200,-2))));
        for x:=1 to 6 do
                for y:=2 to 60 do SG.Cells[x,y]:=StrNew(PChar(floattostr(oroundto(strtofloat(SG.Cells[x,y-1])*(1+jhks/100),-2))));
//        result:=CreateSarry;  //Hier ist es ihm wurscht, ob das dabei ist, oder nicht.
        result:=SG;
end;
Das ist meine wertgebende (die 1. von vielen nachfolgenden, wo ich glaube, wenn ich die knacke, schaff ich auch die anderen leichter ...) Funktion die schon grob Mist baut. Und ich weiß ich wiederhole mich, wenn ich hier erzähl, dass StrNew nirgends irgendwas gebracht hat.

Die function HeadLine: PSarry;// steht in der DLL drin ist in meinem vorherigen Post noch drin. Jetzt geb ich noch die Aufrufprozedur im Host-Programm dazu (also halt der relevante Teil):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure tachange;// steht im Programm drin
begin
  //Hier schicke ich die Variablen in die DLL rüber:
        MainFunctions.SetAllVars(strtofloat(edbgf.Text),  // hat den Wert 135
                                 strtofloat(edep.Text),    // Wert 7
                                 strtofloat(edbtv.Text),  // Wert 80
                                 strtofloat(edjhks.Text),  // Wert 7
                                 cbland.ItemIndex);    // Wert ist 3 aber in meiner gekürzten Version hier irrelevant
  //hier hol ich mir die Überschrift (funzt nicht)
        SG:=MainFunctions.HeadLine;
        for x:=1 to 6 do sgTable.Cells[x,0]:=SG.Cells[x,0];
  //hier hol ich mir die Wertetabelle (funzt nur verdreht/verfälscht)
        SG:=MainFunctions.Heizkost;
        sgTable.RowCount:=61;
        sgTable.Cells[0,0]:=SG.Cells[0,0];
  //um die Überschrift nicht zu zerstören (ist zur Zeit eigentlich auch irrelevant) lass ich die erste Zeile in der for-Schleife weg
        for x:=0 to 6 do
                for y:=1 to 60 do sgTable.Cells[x,y]:=SG.Cells[x,y];
end;
Vielleicht noch erwähnenswert: ich hab (wie wahrscheinlich schon aufgefallen) alle externen Funktionen und Prozeduren in eine neue Unit geschrieben (MainFunctions.pas), damit ich nur eine relativ kleine, übersichtliche Unit habe (eben für Wartung, was sich ja schon gut bezahlt macht :roll: )

Und zur Erklärung der Variabel-Setzung in der DLL:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure SetAllVars(abgf,aenp, abtve, ajhks: real; aland: integer);// steht auch in der DLL drin
begin
        BGF:=abgf;
        ENP:=aenp;
        BTVE:=abtve;
        JHKS:=ajhks;
        Land:=aland;
end;


user profile iconLossy eX hat folgendes geschrieben:
Wenn du debuggst, dann solltest du versuchen dir den Weg der Daten anzuschauen. Und wenn du merkst, dass sie irgendwann anders sind, dann solltest du die zwischenschritte genauer anschauen etc.
Da liegt das Problem: Ich kann es bis zum result:=Sarry; verfolgen, ab dann kommt nur noch Blödsinn raus. Auch Breakpoints im Host-Programm haben ergeben, dass die Werte auf dem Weg ins StringGrid nicht mehr verändert werden. Sie kommen schon Mist ins Programm rein. Obwohl sie in der DLL bis zum Schluss noch logisch und richtig sind.

user profile iconLossy eX hat folgendes geschrieben:
PS: Außerdem würde ich dir empfehlen bei Pointer immer zu dereferenzieren (mit ^). Ich habe schon mal ein paar seltsame Effekte erlebt, wenn man sich darauf verlässt, dass Delphi das immer so hinbekommt.
Na gut, werd ich übernehmen.

Mann, man müsste echt selber Lehrer werden, schon mal um es den Flaschen einfach zu zeigen, wie man es richtig machen könnte :x . Zum Beispiel ganz einfach mal ein Fach unterrichten, das man selber auch versteht.

PS: Muss man vielleicht irgendwelche Dinger wie stdcall oder Ähnliches setzen? Sämtliche Tutorials und Bücher, die ich mir angesehen habe, geben hierzu keine aufschlussreichen Antworten ... Ich beiß mir in den *popo*, wenn es an sowas liegt (was mir aufgrund der nebensächlichen Erscheinungsform, äußerst wahrscheinlich erscheint)

PSS: WOW! Das ist ein Mörder-Beitrag!

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Do 13.03.08 21:31 
Also das was du in ClearSG machst ist zu 100% ein Speicherloch. ;) Zum Lösches eines Wertes solltest du StrDispose aufrufen und den Wert nil setzen aber nicht einen neuen String erstellen.

Die Funktion Heizkosten. Wo kommt das SG eigentlich her und wo wird es erstellt? Außerdem das CreateSarry an der Stelle wo du es auskommentiert hast ist ziemlich unsinnig. Tschuldige falls das zu direkt ist.

Du hast Glück. Ich habe heute einen gute Tag. Ich habe dir mal eine Testanwendung gebaut wie ich das eigentlich angedacht hatte. Schau mal ob du das so ähnlich machst? Ich vermute nicht. Denn in meinem Beispiel gehts 100%tig. Und da ist ein Beispiel wohl besser als 1000 Erklärungen.

Stdcall ist eigentlich nicht zwingend notwendig, wenn beides mit Delphi gemacht wurde allerdings schaden kann es auch nicht. Vermeidet seltsame Effekte falls es mal doch unterschiedlich sein kann.
Einloggen, um Attachments anzusehen!
_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Mi 26.03.08 13:42 
so, osterferien sind wieder vorbei, internet (schule) wieder da ...

zwischenbilanz: ich hab das alles so probiert, wie im beispiel beschrieben, aber bei mir steht die mühle trotzdem. Die fehler heißen alle gleich wie vorher und beim beenden (DestroySG) bekomm ich am ende sogar noch das CPU-Fenster ... was immer das heißen mag ...

ich hab dann ein bisschen überlegt ... und bin genauso schlau wie vorher auch :shock: :eyes:
aber damits nicht umsonst geraucht hat, hab ich mir (jaa, ganz alleine 8) ) ausgedacht, beim ClearSG es doch einfach so zu machen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure ClearSG(Sarry: pSarry); stdcall;
var     x,y:Integer;
begin
        for x:=0 to 6 do
          for y:=0 to 60 do
            if Sarry^.Cells[x,y]<>nil then Sarry^.Cells[x,y]:=StrNew('')
              else Sarry^.Cells[x,y]:='';
end;
was aber das gelbe vom ei nicht sein kann, denn es geht trotzdem nicht

achja: stdcall überall (wow, wo das überall steht ...) bringt auch nichts (trotz der heiden arbeit ...)

in eile
fabs

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Fr 28.03.08 12:18 
Also ich kann dir nur dringenst ans Herz legen dich mehr mit Pointern auseinander zu setzen. Bzw bei Verständnissproblemen in einem Forum dir die Sachen mal erklären zu lassen. ;) Denn versteh das bitte nicht falsch. Aber du hast den "Pfad des Wissens" verlassen und probierst willenlos alle möglichen Kombinationen durch. Und ob das Ergebniss da so berauschend ist lasse ich mal dahin gestellt.

ausblenden Delphi-Quelltext
1:
2:
  if Sarry^.Cells[x,y]<>nil then Sarry^.Cells[x,y]:=StrNew('')
    else Sarry^.Cells[x,y]:='';

Wie ich schon mal gesagt habe. StrNew('') zum Löschen eines Textes ist nicht so toll, denn dadurch wird der Text nicht gelöscht sondern der bestehende Text bleibt erhalten (jegliche Referenz von ihm verschwindet aber im Nichts) und es wird oben drein noch ein neuer Text erstellt. Das Zuweises von '' ist da Sicher schon ein bisschen besser, denn dort wird kein neuer Text erstellt sondern es wird ein Konstanter String benutzt. Aber das Gelbe vom Ei ist es auch nicht.

Das CPU Fenster deutet darauf hin, dass irgendwelche Speicherstellen kaputt sind oder überschrieben wurden etc. Das sollte normal nicht passieren und ist ein deutliches Zeichen!


Das biete ich normal nur eher nur in einem anderen Forum an aber ich denke hier ist es auch nur die einzig sinnvolle Alternative. Denn so gesehen treten wir auf der Stelle und ich weiß nicht was man außer einem Beispielprogramm noch machen soll. Hänge mal bitte deine Anwendung mit allen benötigten Quellen und Dateien an. Wenn das möglich ist. Wenn die Quellen geheim bleiben sollen (was ich nicht vermute), dann kannst du es mir auch per mail ("info (at) opengl24 (punkt) de") schicken. Dann schau ich mir das bei Gelegenheit mal an. Denn langsam gehen mir echt die Ideen aus wie ich es erklären soll. Was bei dem Thema eher ziemlich selten der Fall ist.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
passiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 270

WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
BeitragVerfasst: Fr 11.04.08 08:07 
So jetzt mein Resultat: ich komm nicht weiter ...
Ich werd die DLL einfach über den Haufen werfen. Zu wenig Lust und Zeit dazu.

Trotzdem Danke für die Hilfe.

Vielleicht werd ich das irgendwann mal wieder aufgreifen, aber jetzt geht mir dazu die Zeit aus und es geht ja auch anders.

_________________
Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein