WinFuture-Forum.de: [erledigt] C++ Zeiger Problem - WinFuture-Forum.de

Zum Inhalt wechseln

Nachrichten zum Thema: Entwicklung
Seite 1 von 1

[erledigt] C++ Zeiger Problem delete() notwendig?


#1 Mitglied ist offline   Caprio2L 

  • Gruppe: aktive Mitglieder
  • Beiträge: 116
  • Beigetreten: 08. Januar 07
  • Reputation: 0

geschrieben 30. Juli 2008 - 15:37

Hallo Leute,

ich sitze schon seit Montag an ein und demselben C++-Problem, welches ich kurz schildern möchte.

Situation:
HINWEIS: alles ist stark gekürzt
  • DLL A: erstellt mit Borland C++ Builder; wird von Host-Anwendung geladen; unbedingt notwendig wegen hierin realisierter GUI

  • DLL B: erstellt mit VS 2005; wird von DLL A nachgeladen; einige Funktionen exportiert

  • Daten werden über Zeiger auf struct mit Basis-Datentypen zwischen beiden ausgetauscht

  • struct sieht so aus:
    struct stParameter
    {
    	char cParameterName[MAXPARLENGTH];
    	float fParameterValue;
    	ULONG ulCountCallPath; // Anzahl der Elemente des Parameter-Aufrufpfades
    	ULONG *pulCallPath;	  // Zeiger auf Parameter-Aufrufpfad
    	stParameter()
    	{
    			memset(&cParameterName[0],   0, sizeof(cParameterName));
    			fParameterValue = 0.0F;
    			ulCountCallPath = 0;
    			pulCallPath = NULL;
    		}
    	~stParameter()
    	{
    		if (this->pulCallPath)
    		{
    						delete this->pulCallPath;
    						this->pulCallPath = NULL;
    		};
    	};
    };
    


  • in DLL A wird eine Funktion von DLL B aufgerufen:
    for(i = 0; [...] )
    {
      stParameter *pParList = new stParameter[iParametersCount];
    
      int iGDFP = pDA->dGParFP(pList[i].ulD, pParList, iParametersCount);
      if (iGDFP != -1)
      {
    	  for (int j = 0; j < iParametersCount; j++)
    	  {
    		   stParameter *Para = new stParameter(&pParList[j]);
    		   
    		   ListItem = lvAvailablePar->Items->Add();
    		   ListItem->Caption = Para->cParameterName;
    		   // [...]
    	  }
    	  else
    	  {
    		   sError = "GetParametersFromPlant";
    	  }
    
    	  if (pParList)
    	  {
    		   delete []pParList;
    		   pParList = NULL;
    	  }
      }
    


  • der fragliche Teil der aufgerufenen Funktion in DLL B
    Para->pulCallPath = new ULONG[Para->ulCountCallPath];
    


Problem:
Alles klappt soweit gut, aber beim Löschen von pParList kommt es dann zum Fehler, wenn im Destruktor der Zeiger gelöscht werden soll. Wenn ich das Löschen auskommentiere, klappt wieder alles.

Frage:
Ist der Destruktor von stParameter so korrekt bzw. wird durch Funktion in DLL B der Zeiger im struct dynamisch?

Dieser Beitrag wurde von Caprio2L bearbeitet: 31. Juli 2008 - 15:51

0

Anzeige



#2 Mitglied ist offline   [U]nixchecker 

  • Gruppe: aktive Mitglieder
  • Beiträge: 347
  • Beigetreten: 17. Mai 05
  • Reputation: 0
  • Wohnort:Bayern
  • Interessen:Informatik, Linux, Rollerbladen, Bodybuilding, GungFu

geschrieben 30. Juli 2008 - 23:37

Zitat

Para->pulCallPath = new ULONG[Para->ulCountCallPath];


Du allokierst Speicher in DLL B und möchtest ihn nun in DLL A (über den Destruktor) freigeben, wenn ich das jetzt so richtig verstanden habe?

Das geht aus dem Grunde nicht, da du hier Cross-Module-Allocation betreibst und die DLLs mit unterschiedlichen Compilern erstellt wurden.

Außerdem hast du hier auch noch ein konzeptuelles Problem, was wenn jemand zweimal:

Para->pulCallPath = new ULONG[Para->ulCountCallPath];
Para->pulCallPath = new ULONG[Para->ulCountCallPath];

aufrufst. Dann wird im Destruktor eh nur der Speicher des zweiten Aufrufs freigegeben.
0

#3 Mitglied ist offline   Caprio2L 

  • Gruppe: aktive Mitglieder
  • Beiträge: 116
  • Beigetreten: 08. Januar 07
  • Reputation: 0

geschrieben 31. Juli 2008 - 08:00

Danke für deine Antwort. Ist irgendwie ein ziemlich komplexes Problem, welches du aber richtig erfasst hast.


Zitat

Außerdem hast du hier auch noch ein konzeptuelles Problem, was wenn jemand zweimal:

Para->pulCallPath = new ULONG[Para->ulCountCallPath];
Para->pulCallPath = new ULONG[Para->ulCountCallPath];

aufrufst. Dann wird im Destruktor eh nur der Speicher des zweiten Aufrufs freigegeben.

Die Funktion, in welcher der obige Code enthalten ist, kann nur einmal aufgerufen werden. Dafür habe ich schon gesorgt.


Ich schätze die Frage sollte eigentlich lauten, ob es unsauber ist, wenn ich den Speicher mittels Destruktor nicht freigebe. Bis jetzt lief es im DEBUG-Modus sauber durch. Erst als ich ein RELEASE erstellt habe, klappte es in beiden Fällen nicht mehr.
0

#4 Mitglied ist offline   [U]nixchecker 

  • Gruppe: aktive Mitglieder
  • Beiträge: 347
  • Beigetreten: 17. Mai 05
  • Reputation: 0
  • Wohnort:Bayern
  • Interessen:Informatik, Linux, Rollerbladen, Bodybuilding, GungFu

geschrieben 31. Juli 2008 - 08:28

Zitat

Ich schätze die Frage sollte eigentlich lauten, ob es unsauber ist, wenn ich den Speicher mittels Destruktor nicht freigebe. Bis jetzt lief es im DEBUG-Modus sauber durch. Erst als ich ein RELEASE erstellt habe, klappte es in beiden Fällen nicht mehr.


Im Debug Modus ist die Deallokation von Speicher langsamer, da hier diverse checks gemacht werden. Auch das Threadingverhalten ist ein ganz anderes. Da kommt es im Debug Modus auch ganz leicht vor, dass du z.B. ein free/delete machst und sogar in der nächsten Zeile noch auf den Speicher zugreifen kannst obwohl er eigentlich gar nicht mehr zur Verfügung steht. Bei Threads passierts dann, dass die sich im Debug Modus nie in die Quere kommen und im Release dann auf einmal sich gegenseitig die Pointer um die Ohren hauen.

Zu dem sauber oder nicht, es ist immer sauber dort den Speicher zu deallokieren wo man ihn allokiert hat.

Mir ist gerade noch ein Problem bei dem Ansatz aufgefallen.

Para->pulCallPath = new ULONG[Para->ulCountCallPath];

jetzt macht jemand:

delete Para->pulCallPath

und vergisst ihn auf Null zu setzen, jetzt versuchst du im Desktruktor dein delete und dann schepperts, Verhalten an dieser Stelle ist undefined.

Deshal dort aufräumen wo allokiert wurde, entweder im Objekt allokieren und deallokieren oder eben außerhalb.
0

#5 Mitglied ist offline   Caprio2L 

  • Gruppe: aktive Mitglieder
  • Beiträge: 116
  • Beigetreten: 08. Januar 07
  • Reputation: 0

geschrieben 31. Juli 2008 - 15:51

Habe mein Problem nun gelöst, indem ich die betreffende Variable statisch gemacht habe. Dies war möglich, weil das erst zur Laufzeit erstellte Array später sowieso auf eine gewisse Länge begrenzt wird, weil für eine Parameterübergabe nur begrenzter Speicherplatz zur Verfügung steht.

Danke für die Vorschläge und Hilfe.
0

Thema verteilen:


Seite 1 von 1

1 Besucher lesen dieses Thema
Mitglieder: 0, Gäste: 1, unsichtbare Mitglieder: 0