VC: Nachvollziehen des Recompiling-Problems bei MFC-Erweiterungs-DLLs

13/01/2011 - 09:15 von Dirk Noack | Report spam
Hallo VC-Experten,

ich habe mir vorgenommen einige unserer erstellten und sehr oft
verwendeten Klassen in eine MFC-Erweiterungs-DLL zu packen, um nicht den
Quellcode durch tausende von Projekten zu schleifen.

Im MFC-Tutorial (Part2) von Andrew Fenster wird im Abschnitt
"Recompiling" das Problem beschrieben, dass bestehende Anwendungen einen
Fehler liefern, wenn die DLL erweitert wird ohne Neucompilierung der
Anwendungen. Dieses Problem wollte ich mit einer Testanwendung und einer
Test-DLL nachbilden. Beim Ersetzen der alten DLL mit der neuen
modifizierten DLL hatte ich eigentlich mit einem Crash der
Test-Anwendung gerechnet. Er blieb aber aus. Habe ich irgendwas falsch
verstanden oder wird der Fehler einfach vom System geschluckt?


Auszüge aus meiner Test-DLL:

//MyDllClass.h
#pragma once

class AFX_EXT_CLASS CMyDllClass
{
public:
// Konstruktor(en) (nicht verwenden! -> CreateMe() benutzen)
CMyDllClass(void);
// Destruktor (nicht verwenden! -> DestroyMe() benutzen)
~CMyDllClass(void);

public:
//Methoden
static CMyDllClass* CreateMe(void);
static void DestroyMe(CMyDllClass *pMe);
// wird für modif. DLL aktivert -> Provoz. des Fehlers
// void DoNothing(void) const;
INT DoSomething(const INT nVal1, const INT nVal2) const;

protected:
// wird für modif. DLL aktivert -> Provoz. des Fehlers
// CHAR m_chTest;
INT m_nTest;
// wird für modif. DLL aktivert -> Provoz. des Fehlers
// DOUBLE m_fTest;
};

//MyDllClass.cpp-
#include "StdAfx.h"
#include ".\MyDllclass.h"

CMyDllClass::CMyDllClass(void)
{
}

CMyDllClass::~CMyDllClass(void)
{
}

CMyDllClass* CMyDllClass::CreateMe(void)
{
return(new CMyDllClass);
}

void CMyDllClass::DestroyMe(CMyDllClass *pMe)
{
delete(pMe);
}

INT CMyDllClass::DoSomething(const INT nVal1, const INT nVal2) const
{
// wird für modif. DLL aktivert -> Provoz. des Fehlers
//INT _nTest = 0;

return(nVal1 + nVal2);
}

// wird für modif. DLL aktivert -> Provoz. des Fehlers
/*
void CMyDllClass::DoNothing(void) const
{
}
*/


Auszüge aus meiner Test-Anwendung:


//MainFrm.h--
//
#include ".\MyDllClass.h"

#pragma once
class CMainFrame : public CFrameWnd
{
protected: // Nur aus Serialisierung erstellen
CMainFrame();
...
public:
afx_msg void OnBtnTest();
afx_msg void OnBtnTest2();
afx_msg void OnBtnTest3();
afx_msg void OnBtnTest4();

protected: // Eingebundene Elemente der Steuerleiste
...
CMyDllClass m_cMyDllClass;
INT m_nVal1;
INT m_nVal2;
...
};


//MainFrm.cpp--
//
CMainFrame::CMainFrame()
{
// TODO: Hier Code für die Memberinitialisierung einfügen
m_nVal1 = 99;
m_nVal2 = 88;
}

void CMainFrame::OnBtnTest()
{
// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
CMyDllClass* _pMyDllClass = NULL;
CString _sBuffer(_T(""));

// sollte eigentlich crashen, weil nicht CreateMe()/DestroyMe() benutzt
_pMyDllClass = new CMyDllClass();
_sBuffer.Format("%d + %d = %d", m_nVal1, m_nVal2,
_pMyDllClass->DoSomething(m_nVal1, m_nVal2));
AfxMessageBox(_sBuffer, MB_ICONINFORMATION | MB_OK);
delete(_pMyDllClass);
_pMyDllClass = NULL;
}

void CMainFrame::OnBtnTest2()
{
// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
CMyDllClass* _pMyDllClass = NULL;
CString _sBuffer(_T(""));

// sollte/muss funktionieren
_pMyDllClass = CMyDllClass::CreateMe();
_sBuffer.Format("%d + %d = %d", m_nVal1, m_nVal2,
_pMyDllClass->DoSomething(m_nVal1, m_nVal2));
AfxMessageBox(_sBuffer, MB_ICONINFORMATION | MB_OK);
CMyDllClass::DestroyMe(_pMyDllClass);
_pMyDllClass = NULL;
}

void CMainFrame::OnBtnTest3()
{
// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
CMyDllClass _cMyDllClass;
CString _sBuffer(_T(""));

// sollte eigentlich crashen, weil nicht CreateMe()/DestroyMe() benutzt
_sBuffer.Format("%d + %d = %d", m_nVal1, m_nVal2,
_cMyDllClass.DoSomething(m_nVal1, m_nVal2));
AfxMessageBox(_sBuffer, MB_ICONINFORMATION | MB_OK);
}

void CMainFrame::OnBtnTest4()
{
// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
CString _sBuffer(_T(""));

// sollte eigentlich crashen, weil nicht CreateMe()/DestroyMe() benutzt
_sBuffer.Format("%d + %d = %d", m_nVal1, m_nVal2,
m_cMyDllClass.DoSomething(m_nVal1, m_nVal2));
AfxMessageBox(_sBuffer, MB_ICONINFORMATION | MB_OK);
}
 

Lesen sie die antworten

#1 Stefan Kuhr
13/01/2011 - 09:16 | Warnen spam
Hallo Dirk,

On 1/13/2011 9:15 AM, Dirk Noack wrote:
Hallo VC-Experten,

ich habe mir vorgenommen einige unserer erstellten und sehr oft
verwendeten Klassen in eine MFC-Erweiterungs-DLL zu packen, um nicht den
Quellcode durch tausende von Projekten zu schleifen.





Bitte sieh es mir nach, dass ich die Zeit nicht habe, Dein Problem zu
debuggen, aber wenn Du Dir schon bewusst bist, dass exportierte Klassen
und MFC Extension DLLs zu Problemen fuehren koennen (dass Du Dich vorher
darueber informierst anstatt es einfach zu tun, weil es halt geht, ist
sehr loeblich), warum willst Du das dann ueberhaupt tun? Ich finde
Sourcecode mitschleifen in Tausenden Projekten eine Supersache, man
nennt das common code. Ich leide taeglich und seit Jahren darunter, dass
in unserem Code tonnenweise und zum Teil voellig unnoetig Klassenexporte
in MFC extension DLLs drin sind. Das ist ein Wartungsalptraum, denn
sobald ein Patch fuer eine Funktionalitaet noetig ist, muss man
hoellisch aufpassen, ja nichts am Binaeren Interface zu aendern und man
muss mitunter zu absurden Kunststueckchen greifen, um das gewuenschte
Ergebnis zu erreichen.

Meine Empfehlung: Finger weg! Been there, done that.

S

Ähnliche fragen