TADOConnection verursacht Memory Leak
-
Hallo,
seit einiger Zeit bin ich auf der Suche nach einem Fehler in Verbindung mit der TADOConnection Komponente.
Ich benutze diese um Verbindung zu einer Datenbank zu bekommen. Dazu habe ich eine Funktion, welche eine
Verbindung zu einer Datenbank herstellen soll. Wenn die Verbindung hergestellt werden kann ist alles OK.
Falls aber nicht, weil z.B. die MDB-Datei fehlt oder der Netzwerkserver nicht antwortet, bekomme ich beim
Beenden des Programms laut MadExcept einen MemoryLeak.Folgende Funktionen werden dabei verwendet:
DataModul Header Datei://--------------------------------------------------------------------------- #ifndef DataModulH #define DataModulH //--------------------------------------------------------------------------- #include <System.Classes.hpp> #include <Data.DB.hpp> #include <Data.Win.ADODB.hpp> #include <Xml.Win.msxmldom.hpp> #include <Xml.XMLDoc.hpp> #include <Xml.xmldom.hpp> #include <Xml.XMLIntf.hpp> //--------------------------------------------------------------------------- class TDataModule1 : public TDataModule { __published: // Von der IDE verwaltete Komponenten TADOConnection *actDataService; TADODataSet *adsDataService; TADOQuery *aqrDataService; private: // Benutzer-Deklarationen void SetupDatabaseComponents(); // Setup the Database Components for internal use public: // Benutzer-Deklarationen __fastcall TDataModule1(TComponent* Owner); __fastcall ~TDataModule1(); bool ConnectDatabase(const UnicodeString sServerType, const UnicodeString sServerName, const UnicodeString sUserName, const UnicodeString sPassword, const UnicodeString sDatabase); }; //--------------------------------------------------------------------------- extern PACKAGE TDataModule1 *DataModule1; //--------------------------------------------------------------------------- #endif
DataModul CPP-Datei:
//--------------------------------------------------------------------------- #pragma hdrstop #include "DataModul.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma classgroup "System.Classes.TPersistent" #pragma resource "*.dfm" TDataModule1 *DataModule1; void TDataModule1::SetupDatabaseComponents() { // Einstellungen fuer die Datenbank Verbindungs Komponente actDataService->Close(); actDataService->ConnectionString = ""; actDataService->CursorLocation = clUseClient; actDataService->KeepConnection = true; actDataService->LoginPrompt = false; // Einstellungen fuer die Datenbank Query Komponente aqrDataService->Active = false; aqrDataService->SQL->Clear(); aqrDataService->CursorLocation = clUseClient; aqrDataService->ParamCheck = false; aqrDataService->Connection = actDataService; // Einstellungen fuer die Datenbank DataSet Komponente adsDataService->Active = false; adsDataService->CursorLocation = clUseClient; adsDataService->ParamCheck = false; adsDataService->Connection = actDataService; } bool TDataModule1::ConnectDatabase(const UnicodeString sServerType, const UnicodeString sServerName, const UnicodeString sUserName, const UnicodeString sPassword, const UnicodeString sDatabase) { bool bResult = true; // besteht bereits eine Verbindung zu einer/einem Datenbank/Server if (actDataService->Connected) { // ja, diese dann schließen actDataService->Close(); } if (sServerType.LowerCase().Pos("(*.mdb)")) { // Verbindungsdaten fuer eine lokale Access2000 kompatible Datenbank actDataService->ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=TPOlcldb.mdb"; actDataService->Provider = "Microsoft.Jet.OLEDB.4.0"; } else if (sServerType.LowerCase().Pos("mysql")) { // Verbindungsdaten fuer einen MySQL Netzwerk Datenbank-Server actDataService->ConnectionString = "DRIVER={" + sServerType + "};SERVER=" + sServerName + ";Network=DBMSSOCN;" + "DATABASE=" + sDatabase + ";UID=" + sUserName + ";PWD=" + sPassword + ";OPTION=3"; actDataService->Provider = "MSDASQL"; } else if (sServerType.LowerCase().Pos("sql server")) { // Verbindungsdaten fuer einen MS-SQL(2005/2008) Netzwerk Datenbank-Server actDataService->ConnectionString = "Driver={" + sServerType + "};Server=" + sServerName + ";Network=DBMSSOCN;" + "Database=" + sDatabase + ";User ID=" + sUserName + ";Password=" + sPassword; actDataService->Provider = "SQLNCLI10"; } else { // kein gueltiger Server Treiber angegeben return (false); } try { // und mit den neuen Verbindungsdaten wieder oeffnen actDataService->Open(); } catch (...) { actDataService->Close(); bResult = false; } return (bResult); } //--------------------------------------------------------------------------- __fastcall TDataModule1::TDataModule1(TComponent* Owner) : TDataModule(Owner) { SetupDatabaseComponents(); }
sowie Hauptprogramm Header-Datei:
// --------------------------------------------------------------------------- #ifndef TestMainFormH #define TestMainFormH // --------------------------------------------------------------------------- #include <System.Classes.hpp> #include <Vcl.Controls.hpp> #include <Vcl.StdCtrls.hpp> #include <Vcl.Forms.hpp> #include <Vcl.ComCtrls.hpp> // -------------------------------------------------------------------------- class TForm1 : public TForm { __published: // Von der IDE verwaltete Komponenten TButton *Button1; TButton *Button2; TButton *Button3; void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); void __fastcall Button3Click(TObject *Sender); private: // Anwender-Deklarationen public : // Anwender-Deklarationen __fastcall TForm1(TComponent* Owner); }; // --------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; // --------------------------------------------------------------------------- #endif
und Hautpprogramm CPP-Datei:
// --------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "TestMainForm.h" #include "DataModul.h" // --------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; // --------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { try { DataModule1 = new TDataModule1(NULL); } catch (...) { // } } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { try { delete DataModule1; DataModule1 = NULL; } catch (...) { // } } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { // pruefe das Vorhandensein einer lokalen Datenbank if (!DataModule1->ConnectDatabase("Microsoft Access Driver (*.mdb)", "", "", "", "")) { // es ist keine gueltige lokale Datenbank vorhanden MessageDlg("MSG_LOCAL_DATABASE_MISSING", mtInformation, TMsgDlgButtons() << mbOK, 0); } } //---------------------------------------------------------------------------
und zum Schluß der Memory-Leak Report von MadExcept:
allocation number: 2308 program up time: 5,04 s type: GetMem address: $bddf3f0 size: 28 access rights: read/write main thread ($a9c): 671ca339 madExcept32.dll madExceptDbg 1453 GetMemCallback 0cd01c4a CG32.DLL __cg_malloc 0cd03050 CG32.DLL __cg_new 32c70498 CC32120MT.DLL ___VCL_add_EH 32c7635a CC32120MT.DLL ____ExceptionHandler 00406f68 UniversalTest.exe __ExceptionHandler 7751012e ntdll.dll KiUserExceptionDispatcher 50fcbd1f adortl160.bpl Data.Win.ADODB 1647 TADOConnection.DoConnect 508ee0bd dbrtl160.bpl Data.DB 3159 TCustomConnection.SetConnected 00404a25 UniversalTest.exe DataModul.cpp 88 TDataModule1.ConnectDatabase 00405552 UniversalTest.exe TestMainForm.cpp 47 TForm1.Button3Click 50332d6f vcl160.bpl Vcl Controls.TControl.Click 50337163 vcl160.bpl Vcl Controls.TWinControl.WndProc 50356cf0 vcl160.bpl Vcl Stdctrls.TButtonControl.WndProc 50337163 vcl160.bpl Vcl Controls.TWinControl.WndProc 50449405 vcl160.bpl Vcl Forms.TCustomForm.WndProc 503367b8 vcl160.bpl Vcl Controls.TWinControl.MainWndProc 752096c0 USER32.dll SendMessageW 75210d48 USER32.dll CallWindowProcW 50337260 vcl160.bpl Vcl Controls.TWinControl.DefaultHandler 50337163 vcl160.bpl Vcl Controls.TWinControl.WndProc 50356cf0 vcl160.bpl Vcl Stdctrls.TButtonControl.WndProc 75207885 USER32.dll DispatchMessageW 504524ef vcl160.bpl Vcl Forms.TApplication.ProcessMessage memory dump: 0bddf3f0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 0bddf400 00 00 00 00 00 00 00 00 - 00 00 00 00 ............
Das ist ein wirklich auf das notwendigste zusammengestrichenes Testprojekt, mit welchem sich der Fehler
aber jederzeit reproduzieren lässt. Wäre über Hilfe sehr dankbar.Grüße Netzschleicher
-
Nachtrag:
Ich habe obigen Code im C++Builder XE2 geschrieben. Dort tritt der Fehler auch auf. Auch wenn ich die ADOConnection direkt in dem eigentlichen Fenster verwende ohne das Datenmodul.
Zum Testen habe ich dieses Szenario nun auch im RAD Studio 2007 nachvollzogen. Dort tritt dieser Fehler nicht auf.
Ist das jetzt ein kleiner Bug im XE2 oder hat MadExcept mit dem XE2 probleme?
Wäre nett wenn mir da jemand weiterhelfen könnte.Grüße
-
Hallo an alle,
ich möchte mit aller Höflichkeit mal nachfragen ob zu meinem Problem keiner eine Idee oder Lösungsvorschlag hat. Vielleicht mache ich ja auch bei der 'try - catch' Konstruktion einen Fehler? Wie schon beschrieben tritt der Fehler beim Beenden nur unter C++ XE2 auf, nicht unter C++ 2007. Falls es an dem MadExcept liegen sollte, dann kann ich damit auch leben. Falls das aber doch wieder so eine Verschlimmbesserung im C++ XE2 ist, spiele ich mit dem Gedanken den C++ XE2 nicht mehr zu nutzen und bleibe lieber beim C++ 2007. Evtl. werd ich mich dann auch vom C++ XE2 trennen.
Grüße Netzschleicher
-
Hi,
hab mir deinen Code jetzt mal durchgelesen und habe nichts sehen können, was auf ein MemLeak hinweisst.
Interessant wären evtl. noch dein Kon-/Destruktor von DataModule1, sowie die Klasse TDataModule von der du ja TDataModule1 ableitest, vielleicht ist da was zu finden.mfg
-
Ich glaube nicht das es an dem Datenmodul liegt. Wie ich schon angedeutet habe, tritt der Fehler auch auf wenn die ADO-Komponenten
direkt in der Form liegen und dort auch aufgerufen werden. Ich vermute eher das bei den Erweiterungen der VCL im Builder XE2
irgendwo ein kleiner Fehler sich eingeschlichen hat. Was natürlich sehr böse wäre.
Wie schon geschrieben, im RAD-Studio 2007 läuft das alles ohne einen einzigen Fehler.