![]() |
Pointer vom String übergeben und ändern
Hallo,
hab ein kleines Problem mit einem Pointer. Verwende sie öfter aber an der einen Stelle knallt's ab und zu (unregelmäßig). Ich veruche vom Hauptprogramm an eine DLL eine Adresse von einem String zu übergeben, diesen in einer Variable zu speichern und dann als Rückgabewert wieder ins Programm einzuschleusen:
Delphi-Quellcode:
Wie gesagt. Ab und zu gehts, ab und zu kommt die Meldung
Hauptprogramm:
var s: String; begin s:=Hallo; dllprozedur(@s); end; DLL function dllprozedure(s: PString): String; stdcall; var localS: String: begin localS:=s^; localS:=localS+'sdsd'; return:=localS; end; Zugriffverletzung bei Adresse 0164F144. Lesen von Adresse 0164F144 Wenn ich das Programm neustarte, gehts wieder... |
Re: Pointer vom String übergeben und ändern
Benutzt du den Borland Memory-Manager?
Was ist reutrn? Gibt s das tatsächlich? Ist mir zumindest neu. ich benutze immer result, alasse mich aber gerne belehren :P Hast du schonmal daran gedacht, eventuell PChars zu benutzen, statt Strings? Dann könntest du auf die aufgebläht borlndmm.dll verzichten. |
Re: Pointer vom String übergeben und ändern
Hi,
ich habe mich geirrt. Return heißt es in PHP - verwechsle das gerne. Den MemoryManager benutze ich nicht. Allerdings passiert das auch bei PChars... Ein PChar ist ja auch nur ein Pointer... :wall: |
Re: Pointer vom String übergeben und ändern
@DJ-SPM: doch tust du ;)
Der DelphiMemoryManager / BorlandMM (wird standardmäßig in Delphiprogrammen verwendet) erstellt für jedes Moul eine eigenstänfdige Instanz, welche nur ihren eigenen Speicher verwalten kann. Es wird also jeweils für die EXE und die DLL ein eigener MemoryManager verwendet. Der Speicher für die Strings wird beim lokalen MemoryManager reserviert. Demnach ist es nicht möglich einen String von einem Modul an ein Anderes zu übergeben. Denn wenn der MM versucht den Speicher eines Strings auf 'nem anerem Modul zu veränder/freizugeben, dann kracht es halt, da der Speicherblock wo der String drin ist ja dem anderem MM gehört. Fazit: sowas ist nicht möglich. Lösung: ein alternativer Shared-MemoryManager wie z.B. FastMM. FastMM kann sich ProgrammGlobal initialisieren, also nur einmal für alle Module welchen ihn verwenden. Oder du holst dir den Speicherblock direkt von Windows, oder sorgs dafür daß der Speicherblock nicht Modulübergreifend verändert wird.
Delphi-Quellcode:
var s: String[255]; < Wichtig: keine dynamischen Strings
begin s:=Hallo; dllprozedur(@s); end; procedure dllprozedure(var s: String[255]); begin S:=S+'sdsd'; end; PS: WideString ist derzeit (ich hoffe das ändert sich bald endlich mal) keine delphieigene Struktur. Bei Diesem wird intern alles, was das Speichermanagement angeht, auf einen OLE-String umgeleitet und demnach von der ole32.dll verwaltet. Da es die ole32.dll nur einmal im Programm gibt wird demnach ebenfalls die gesamte Verwaltung nur von dieser DLL übernommen und ist somit auch ohne einen alternativen MemoryManager Modulübergreifend (die ole32.dll hat sozusagen ihren eigenen MM eingebaut) |
Re: Pointer vom String übergeben und ändern
Ja, so mache ich es doch. Mir ist aufgefallen, (und so habe ich es jetzt auch gelöst, dass wenn ich die DLLs immer wieder freigebe wenn ich sie nicht brauche und dann wieder lade, wenn ich sie brauche, alles funktioniert. Ist zwar eine seltsame Lösung, aber das klappt.
Was mich irritiert ist, dass ich mehrere DLLs habe, mit denen ich auf gleiche Art und Weise die Strings übergebe und es da nie Probleme gab. Immer nur mit der einen DLL. Da scheint der Wurm / Bug drin zu sein. Ansosnten habe ich es ja richtig gemacht... Die String sind die Länger als 255 Zeichen, obwohl das auch geht. Habe ich schon probiert. Oder irre ich mich da? |
Re: Pointer vom String übergeben und ändern
Es kommt auf den Sringinhalt an.
z.B.
Delphi-Quellcode:
Du siehst daß nicht immer Daten im Speicher/RAM liegen, oder gar an der Speicherverwaltung was geändert wird.
// Pointer(S) = nil
S := ''; // Pointer(S) = ziegt direkt auf den Datenbereich, wo '1234' im Programmcode gespeichert ist S := '1234'; // Pointer(S) = Pointer(S2) ... wobei hier nur der Referenzzähler geändert wird S := S2; // neuer String wird resserviert und die gesamten Stringdaten werden da reinkopiert // die alten Stringdaten werden freigegeben S := S + '12'; S := S2; UniqueString(S); // das Selbe wie bei S := S2; // nur daß hier noch die Stringdaten nachträglich in einen eigenen Datenbereich // kopiert und natürlich der Refferenzzähler wieder zurückgesetzt wird ... Demnach kann es auch mal keine Probleme geben. Probleme tauchen nur auf wo die Speicherverwaltung, also hier speziell BorlandMM ins Spiel kommt. Also es ist ganz einfach ... solange man getrenne Speichermanager verwendet sollta man nicht an den speicherverwaltung veränderntes über Modulgrenzen hinweg machen. Aber wenn man weiß was intern wirklich passiert, dann kann man eventuelleinige "eigenarten" ausnutzen. z.B. geht sowas, da hierbei der MM nicht ins Spiel kommt.
Delphi-Quellcode:
procedure dllprozedure(const s: String);
var s2: string; begin s2 := s; UniqueString(s2); // Ab hier kann dan mit S2 alles gemacht werden, was man // will, egal von wo S an diese Prozedur übergeben wurde. // Selbst über die Grenzen der Prozedur hinaus ... solange // der String innerhalb des Moduls (EXE/DLL) verbleibt. ... end; function dllprozedure(const s: string): string; begin if s = '123' then result := 'irgendwas' else if s = '456' then result := 'nochwas' else result := 'keinen plan'; end; |
Re: Pointer vom String übergeben und ändern
Ja, die Erfahrung musste ich halt machen - da bin ich mit Sicherheit auch nicht der eingige *g*. Nur schon seltsam, dass ein neuladen der DLL dieses Problem wieder behebt. Selbst wenn ich die Pointer mit s:=nil freigebe, funktioniert es nicht ohne entladen und erneutes laden der DLL.
ACHSO: ShareMem ist nicht eingebunden - nirgends. |
Re: Pointer vom String übergeben und ändern
hab oben noch was nachgetragen ^^
wie entlädst du die DLLs? und du bist dir sicher, daß du dir keine speicherlecks einhandelst? und solltest du besser mal, jedenfalls wenn du sowas machst (ShareMem, oder vergleichbares) schließlich merkst du ja die Probleme ohne diesen. |
Re: Pointer vom String übergeben und ändern
Das Beispiel schaue ich mir nochmal an - also das, was du oben nachgetragen hast.
Ich entlade die DLLs mit FreeLibrary (habe sie dynamsich geladen und die Handles gespeichert). Und ich habe sogar FastMM4 eingebunden wleches mir in KEINEM meiner Module Speicherlecks anzeigt. Habe immer alles brav beseitigt. Wie gesagt, ich verstehe es selbst nicht. |
Re: Pointer vom String übergeben und ändern
Hast du FastMM auch auf SharedMemory umgestellt?
(in der entsprechenden .inc) Wenn ich mich recht erinnere ist dieses ja per Standard deaktiviert. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz