DLL & Speicherauslastung
-
Entsprechend deines Quelltextauszuges lädst und entlädst du die dll bei jedem Aufruf von ImpWait. Ich meinte, dass du die dll nur einmal, beim Start deines Programmes lädst.
Wozu dient eigentlich das prozessmessages nach dem Sleep?
-
Braunstein schrieb:
Entsprechend deines Quelltextauszuges lädst und entlädst du die dll bei jedem Aufruf von ImpWait. Ich meinte, dass du die dll nur einmal, beim Start deines Programmes lädst.
Achso, die Dll gleich laden und die Dll-Fkt erst bei Bedarf - und dann ist das ganze noch dynamisch? Dann hab' ich wohl im Tutorial was falsch verstanden?

Braunstein schrieb:
Wozu dient eigentlich das prozessmessages nach dem Sleep?
Na wenn Du schon so fragst: hab' ich gar nicht drüber nachgedacht, als ich die Fkt aus meinem Prog in die Dll kopiert habe... Bei näherer Betrachtung ergibt das extrem wenig Sinn an dieser Stelle!
DankePS - Frage am Rande: Wo finde ich eigentlich Info's darüber, wo das Forum die letzten 2 Tage war? Hab noch nie davon gehört das ein Forum in Urlaub fährt...
-
Hallo
Kolumbus schrieb:
Braunstein schrieb:
Entsprechend deines Quelltextauszuges lädst und entlädst du die dll bei jedem Aufruf von ImpWait. Ich meinte, dass du die dll nur einmal, beim Start deines Programmes lädst.
Achso, die Dll gleich laden und die Dll-Fkt erst bei Bedarf - und dann ist das ganze noch dynamisch? Dann hab' ich wohl im Tutorial was falsch verstanden?

Ja das ist noch dynamisch. Statisch wäre komplett ohne LoadLibrary, sondern über eine lib-Datei
PS - Frage am Rande: Wo finde ich eigentlich Info's darüber, wo das Forum die letzten 2 Tage war? Hab noch nie davon gehört das ein Forum in Urlaub fährt...
Siehe hier.
bis bald
akari
-
Nur zum Verständnis - im Tutorial steht:
BCB-Tutorial schrieb:
Als nächsten Schritt wechseln wir zur Unit DLLImp.cpp. Hier erfolgt die Implementierung der ... Schnittstellen-Funktionen ... (diese Funktionen könnten natürlich auch einen beliebig anderen Namen erhalten):
int AddVals(int x, int y) { TAddVals* AddVals; //Variable des Zeigertyps. int Erg; HINSTANCE h = LoadLibrary("Project2.dll"); //DLL wird bei Bedarf geladen. //============================ if (h != 0) AddVals = (TAddVals*)GetProcAddress(h, "_AddVals"); if (AddVals != NULL) Erg = AddVals(x, y); //Aufruf der DLL-Funktion, hier also kein rekursiver Aufruf. else Erg = 0; FreeLibrary(h); //..und nach Gebrauch entladen. //============================= return Erg; }Warum steht das dann so im Tutorial, wenn es nicht richtig ist?

Meine Import.cpp (gleichwertig mit DllImp.cpp im Tut) nochmal:
// Project1.exe->Import.cpp #pragma hdrstop #include "Import.h" //--------------------------------------------------------------------------- #pragma package(smart_init) void ImpWait(int W) //RS| Definition der Schnittstellenfunktion { TWait* WaitAdr= NULL; // !!!!!!!!!!!!!!!! FEHLER??? !!!!!!!!!!!!!!! HINSTANCE HI= LoadLibrary("DynDll.dll"); if (HI != 0) { WaitAdr = (TWait*)GetProcAddress(HI, "_Wait"); } if (WaitAdr != NULL) WaitAdr(W); FreeLibrary(HI); }Kann es sein dass ein weiterer Fehler einfach da liegt, wo ich die vielen Ausrufezeichen gemacht habe? wenn ja, warum?
-
Ich habe nicht gesagt, dass das nicht richtig ist. Nur recht ineffektiv, wenn du die Funktion häufig brauchst.
Das, wo bei dir Fehler dran steht, ist keiner. Ich würde es nur ein wenig anders machen.void ImpWait(int W) //RS| Definition der Schnittstellenfunktion { HINSTANCE HI= LoadLibrary("DynDll.dll"); if( HI == 0) return; // Wenn die Bibliothek nicht geladen werden kann, kann man doch gleich rausgehen (evtl. Rückgabewert ?) TWait* WaitAdr = reinterpret_cast<TWait*>(GetProcAddress(HI, "_Wait")); //Ich benutze liber C++Casts statt C-Casts if( WaitAdr) WaitAdr(W); FreeLibrary(HI); }
-
Braunstein schrieb:
Nur recht ineffektiv, wenn du die Funktion häufig brauchst.
Ich kapier' das einfach nicht... Ich hab das Projekt zur Übung für spätere große Projekte gemacht - da stehen dann viele Fkt.en in einer Dll und die werden auch nicht ständig aufgerufen, sondern teilw. wahrscheinlich bloß 1-2Mal pro Anwendung (die Dll soll ja Fkt.en für mehrere Anwendungen zur Verfügung stellen). Und egal wie oft ich eine Dll-Fkt aufrufe - wenn sie dynamisch ist, muss sie doch auch wieder vollständig entladen werden!?! Da darf sich doch nix aufsummieren im Speicher!?! Erst recht nicht 1000k!?!

Und meine jetzige 2Button-Zähler-Anwendung ist doch nur ein kleines Testprog...
(Hand aufs Herz - wer bräuchte da ne dll mit ner Fkt sleep(int w)?)Braunstein schrieb:
Ich benutze liber C++Casts
Ich habe keine Ahnung was Casts sind!
Kannst Du das ein einem Satz darstellen?
-
z.Bsp.
Die Funktion GetProcAddress liefert als Ergebnis einen void-Zeiger (void*). Der kann auf so ziemlich alles zeigen, verwenden kannst du ihn aber so noch nicht. Du musst diesen void-Zeiger erst in einen Zeiger auf TWait umwandeln. Dieses Umwandeln nennt man auch einen Cast.
Du machst hier also nichts weiter, als deinem Compiler zu sagen
"Klar, das ist ein void-Zeiger. Ich weiß aber genau, das das eigentlich ein TWait-Zeiger ist, also behandle ihn auch so"
In deinem fall kann man auf zwei verschiedene Arten umwandeln
Die C-MethodeWaitAdr = (TWait*)GetProcAddress(HI, "_Wait");Die C++-Metode
TWait* WaitAdr = reinterpret_cast<TWait*>(GetProcAddress(HI, "_Wait"));Weiteres hierzu
http://tutorial.schornboeck.net/casts.htm
http://tutorial.schornboeck.net/reinterpret_cast.htm
http://tutorial.schornboeck.net/dynamic_cast.htm
-
So, ich habe jetzt mal Einiges versucht umzusetzen, was Ihr gepostet habt:
1. Ich benutze jetzt auch den C++ Cast. Die Tutorials hab' ich noch nicht gelesen, aber ich hoffe es findet sich dort bei späterem Lesen eine Erklärung, warum der C++ Cast besser ist (der C Cast ist nämlich eigentl. übersichtlicher, also leichter zu merken finde ich). Danke für die Erklärung zu casts!
2. Die dll wird jetzt nur beim Aufruf der Btn2-Klick-Behandlg. 1x geladen und 1x am Ende der Fkt entladen.
3. Das return; im Fehlerfall habe ich eingebaut, natürlich ist es sinnvoll dann abzubrechen!
Zusätzlich hab' ich vorm return ne Fehlermeldung über eine MessageBox eingebaut, falls die dll nich geladen werden kann. Warum MessageBox?throw std::logic_error("Cannot load *.dll");hat leider eine Fehlermeldung gebracht: [C++ Fehler] Anwendg.cpp(48): E2316 'logic_error' ist kein Element von 'std'
Ergebnisse (*prey* - es gibt Ergebnisse!):
* Die Speicherauslastung steigt nur noch beim 1. Starten der Zählschleife mit dll-delay um ca. 600k, dann immer so zw. 4 und 12k pro Durchlauf (reicht auch noch!)... bewege mich damit insgesamt im 4000k-Bereich, bei unbelasteter VCL-Anwendg.
* Die Anwendung funktioniert noch, inklusive beider Zählschleifen.
Fragen:
* Wie kann ich die Speicherauslastung noch weiter senken? Oder war's das?
(die 600k mehr nach dem 1. Starten der Dll-Fkt sind mir noch zuviel....)
* Ich hab einen Tip bekommen der hieß: "CodeGuard benutzen!" was sagt Ihr dazu?
* Ich hätte mir gerne die Speicherauslastung in einem Label anzeigen lassen, damit ich nicht immer den TaskMgr öffnen muss - gebt Ihr mir dazu einen Hinweis? (Ich mach' aber auch gern nen neuen Thread auf...
)MfG
Ein sehr dankbarer Entdecker
-
zu 1.
Vielleicht leichter zu merken, aber viel schwerer im Code zu finden. Zudem wandelt ein C-Cast immer um, egal ob das wirklich geht oder nicht. In deinem Fall ist das zwar egal, in den meisten andreren Fällen aber nicht.zu 3.
Bau mal ein#include <stdexcept>mit ein. Dann sollte es gehen.
Um die 600k wirst du wohl nicht rumkommen.
CodeGuard ist immer eine gute Idee. Solange die Projekte noch klein sind kannst du damit leicht Fehler finden.
Standardmäßig gibt es (glaube ich) nichts um die Speicherauslastung anzuzeigen. Es gibt aber genug externe Komponenten, die das können. Einfach mal suchen. Ich würde in einem solchen Fall wohl die LMD-Tools nehmen.
-
Kolumbus schrieb:
1. Ich benutze jetzt auch den C++ Cast. Die Tutorials hab' ich noch nicht gelesen, aber ich hoffe es findet sich dort bei späterem Lesen eine Erklärung, warum der C++ Cast besser ist (der C Cast ist nämlich eigentl. übersichtlicher, also leichter zu merken finde ich).
http://c-plusplus.net/forum/viewtopic-var-p-is-1254559.html#1254559
-
Ok, Danke ihr Beiden - so langsam fügt sich ein Bild, wenn auch noch sehr verschwommen - ich erkenne schon langsam die Familie cast...
Braunstein schrieb:
#include <stdexcept>dann war ich ja mit dem Versuch
#include <stdio>schon auf dem richtigen Weg... (auch wenn's noch n paar Meter entfernt ist).
Aber ich werd's mal testen, Danke!Edit: Der Dll-Ladefehler gefällt mir mit ner MessageBox besser - da kenn ich mich mit aus und da steht nicht nur "Externe Exception EEFFACE" drin... Warum sollte ich noch extra ne Datei includieren, wenn's auch so geht? Oder habe ich davon Vorteile?
Braunstein schrieb:
CodeGuard ist immer eine gute Idee. Solange die Projekte noch klein sind kannst du damit leicht Fehler finden.
Auch das werde ich dann bei Gelegenheit mal in Angriff nehmen. Viell. hilfts mir ja dann doch bei mittelgroßen Projekten auch?!
Zum Thema Speicherauslastung: Hab da im msdn was von GetCurrentProcess / GetProcessWorkingSet / GetProcess... gefunden, ist davon nich was zum Speicherauslastung anzeigen. GetProcessWorkingSetSize ist ja irgendwie für Minimum und Maximum des physikalischen Speichers, nicht für die aktuelle Gesamt-Auslastung!?!

Wenn es innerhalb der üblichen Anweisungen möglich wäre, wär' mir schon lieber als externe Komponenten...
-
So, hab jetzt mal folgendes in mein Prog eingebaut:
HANDLE hCurProc= GetCurrentProcess(); DWord ProcID= GetCurrentProcessId(); Label1->Caption= ProcID; //Anzeige der Prozess-ID bool WSISucceed; int kMaker= 1024; unsigned long MinMem=0; unsigned long MaxMem=0; unsigned long *pMinMem= &MinMem; unsigned long *pMaxMem= &MaxMem; WSISucceed= GetProcessWorkingSetSize(hCurProc, pMinMem, pMaxMem); if (WSISucceed== 1) { Label2->Caption= IntToStr(*pMinMem / kMaker) + "k"; //Anzeige der WorkingSetSize Label3->Caption= IntToStr(*pMaxMem / kMaker) + "k"; } PROCESS_MEMORY_COUNTERS P_M_C; GetProcessMemoryInfo(hCurProc, &P_M_C, sizeof(P_M_C)); Label4->Caption= P_M_C.PagefileUsage; //Anzeige der Speicherauslastung CloseHandle(hCurProc);nur leider bekomme ich folgende Fehlermeldung:
[Linker Fehler] Error: Ungelöste externe 'GetProcessMemoryInfo' referenziert von C:\...\DLL-PROJEKT\DEBUG_BUILD\ANWENDG.OBJ
seit ich diesen Code dazugeschrieben habe:
PROCESS_MEMORY_COUNTERS P_M_C; GetProcessMemoryInfo(hCurProc, &P_M_C, sizeof(P_M_C)); Label4->Caption= P_M_C.PagefileUsage; //Anzeige der Speicherauslastung#include "PSAPI.h"hab' ich auch drin.
Jetzt hatte ich schon fast Hoffnung, dass mein Prog seine Speicherauslastung anzeigt...
Oder ist PagefileUsage wieder nicht die Speicherauslastung? Wo könnte das Problem liegen?
-
Binde mal die Psapi.lib mit in dein Projekt ein. Die dürfte unter deinem Builderverzeichnis\Lib\Psdk liegen.
-
Das genannte Verzeichnis ist vorhanden, die psapi.lib ist drin und das Verzeichnis ist als Bibliothekssuchpfad in den Linkeroptionen angegeben... Was fehlt?
-
Hallo
Du must die genannte lib noch über Projekt/Dem Projekt hinzufügen einbinden (Dateityp im Dialog auf lib stellen)
bis bald
akari
-
Super, Danke - so funzt das!

Und wenn ich das Prog jetzt woanders nutzen will, muss ich die PSAPI mitliefern?
Edit: Nö

{ close("Dll & Speicherauslastung"); }