Probleme bei C++ Objekten im prozessübergreifenden, globalen Speicher.



  • Windows 7 Professional, 64 Bit, Service Pack 1 mit Visual cpp 20005.

    Probleme bei Aufruf virtueller Funktionen von Objekten, die im prozessübergreifenden globalen Speicher angelegt sind.

    Abläufe:

    In DllMain(...) wird mit hilfe der Funktionen
    CreateFileMapping(...) bzw. OpenFileMapping(...) und
    MapViewOfFile (...) globaler Speicher creiert.
    Alle Prozesse, die nachfolgend gestartet werden, können auf den Inhalt dieses creierten globalen Speicher zugreifen.

    In main() von startUp.exe wird im globalen Speicher ein Objekt der Klasse KoordMsg konstruiert.
    Beispiel:
    // Die Anfangsadresse des globalen Speicher ermitteln
    void (*pBaseAddr) (GetBaseAddr());
    KoordMsg koordMsg(1,2,3,4);
    // Das vorher konstruierte Objekt der Klasse KoordMsg
    // an den Anfang des globalen Speicher kopieren.

    Message (*pMessage) (new (pBaseAddr) KoordMsg(koordMsg));

    Message ist eine abstrakte Basisklasse, von Message ist KoordMsg abgeleitet.

    Innerhalb von startUp.exe können die Funktionen der Klasse KoordMsg problemlos aufgerufen werden:

    size_t SizeOf (pMessage->SizeOf());
    size_t dataSize (pMessage->DataSize());
    int koordData (pMessage->GetValue(dataSize, &koordMsg));

    In main() von startUp.exe wird wird anschließend der Client-Prozess textEdit.exe gestartet.
    Wenn jetzt in main() des Client-Prozess textEdit.exe die virtuellen Funktionen der Basisklasse Message aufgerufen werden kommt es zum Absturz:
    // Die Anfangsadresse des globalen Speicher ermitteln
    Message (*pMessage) ((Message *)GetBaseAddr());
    size_t SizeOf (pMessage->SizeOf());
    size_t dataSize (pMessage->DataSize());

    Mit dem Debuger kann man sehen, daß im Objekt der Klasse KoordMsg die virtual functions-Table, auf die __vfptr zeigt, fehlerhaft ist.

    Meine Frage: Was mache ich falsch?
    Muß ich zusätzlich eine Compiler-Option setzen?

    Quellcode

    DllMain-cpp:
    
    #define MSG_DECL
    #define MSGLIB
    
    #include <windows.h>
    #include <stdio.h>
    
    #define DLL_EXP
    
    #include "../include/define.h"
    
    extern "C" BASICPOS_DECL void * GetBaseAddr(void);
    
    extern "C" BASICPOS_DECL size_t GlobMemSize(void);
    
    #undef DLL_EXP
    
    static HANDLE fileMappingHdl (0L);
    
    #define GLOBMEMBASEADDRESSE 0x00520000
    #define C_GLOBMEM 2000
    
    static void (*pBaseAddr) (NULL);
    
    void * GetBaseAddr(void)
    {
        return pBaseAddr;
    }
    
    size_t GlobMemSize(void)
    {
        return C_GLOBMEM;
    }
    
    static void * GlobMemBaseAddr(HANDLE *pFileMappingHdl)
    {
       const char (* pDataFile)("commDataFile");
    
       SECURITY_ATTRIBUTES saFileMap = { sizeof (saFileMap), NULL, FALSE };
    
       void (* pBaseAddr)   (0L);
       HANDLE fileMappingHdl(0L);
    
       size_t memSizeLow(GlobMemSize());
    
       fileMappingHdl = OpenFileMapping(
                       FILE_MAP_ALL_ACCESS,     // read/write access
                       FALSE,                   // do not inherit the name
                       pDataFile);              // name of mapping object
    
       if (fileMappingHdl) {
          fprintf(stdout, "\n OpenFileMapping Hdl = %X, ProcessId = %ld\n",fileMappingHdl, GetCurrentProcessId());
       }
       else {
          SetLastError(0L);
          fileMappingHdl = CreateFileMapping(
                       INVALID_HANDLE_VALUE, // use paging file
                       &saFileMap,	// default security
                       PAGE_READWRITE,  // read/write access
                       0,          // maximum object size (high-order DWORD) 
                       memSizeLow, // maximum object size (low-order DWORD) 
                       pDataFile); // name of mapping object
          if (fileMappingHdl) {
             fprintf(stdout, "\nCreateFileMapping Hdl = %X, ProcessId = %ld\n",fileMappingHdl, GetCurrentProcessId());
    	  }
       }
    
       DWORD fileMappErr (GetLastError());
       if(fileMappErr == ERROR_ALREADY_EXISTS) {
          fprintf(stdout, "\n MAPPING-FILE_ALREADY_EXISTS\n");
          SetLastError(0L);
       }
       else {
          if(fileMappErr != 0) {
             fprintf(stdout, "\n\n CreateFileMapping() ERR\n");
             fprintf(stdout, "\n err = %d\n", fileMappErr);
    	  }
       }
    
       if (fileMappingHdl) {
    
          void (* pfileView)(0L);
    
    //      pfileView  = MapViewOfFileEx (fileMappingHdl, FILE_MAP_ALL_ACCESS, 0, 0, 0, (LPVOID)GLOBMEMBASEADDRESSE);
    
          pfileView  = MapViewOfFile (fileMappingHdl, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    
          DWORD fileViewErr (GetLastError());
    	  if (fileViewErr) {
             pfileView = 0;
             fprintf(stdout, "\n MapViewOfFile(...) war nicht erfolgreich, %ld\n",fileViewErr);
    	  }
    	  else {
             fprintf(stdout, "\nMapViewOfFile, Startadresse %p\n\n\n",pfileView);
    	  }
    
          pBaseAddr = pfileView;
       }
       *pFileMappingHdl = fileMappingHdl;
       return pBaseAddr;
    }
    BOOL WINAPI DllMain( HANDLE /*handle*/, ULONG reason, LPVOID /*reserved*/ )
    {
      static int counte = 0;
      switch ( reason ) {
        case DLL_PROCESS_ATTACH:
    	{
           fprintf (stdout, "\nDLL_PROCESS_ATTACH in msglib\n");
           pBaseAddr = GlobMemBaseAddr(&fileMappingHdl);
    
    	   if (pBaseAddr == 0L) {
              fprintf (stdout, "    ERROR:DLL_PROCESS_ATTACH pBaseAddr = 0L!!\n");
           }
    	}
        break;
    
        case DLL_PROCESS_DETACH: {
           --counter;
    	   void (* pBase)   (GetBaseAddr());
           BOOL resUnmapFileView (UnmapViewOfFile(pBase));
           BOOL resCloseMappHdl  (CloseHandle(fileMappingHdl));
           HANDLE  processEvHdl  (GetCurrentProcess());
           BOOL resCloseEventHdl (CloseHandle(processEvHdl));
    	   pBaseAddr = 0L;
           fprintf (stdout, "DLL_PROCESS_DETACH in msglib,\n");
           fprintf (stdout, "resultUnmapViewOfFile =%d, resultCloseMappingHandle =%d, resultCloseEventHandle =%d\n", resUnmapFileView, resCloseMappHdl, resCloseEventHdl);
        }
        break;
    
        case DLL_THREAD_ATTACH:
           fprintf (stdout, "DLL_THREAD_ATTACH in msglib\n");
        break;
    
        case DLL_THREAD_DETACH:
           fprintf (stdout, "DLL_THREAD_DETACH in msglib\n");
        break;
    
        default:
        break;
      }
      return TRUE;
    }
    IncludeFile define.h:
    
    #undef BASICPOS_DECL
    #ifdef DLL_EXP
    #  define BASICPOS_DECL __declspec(dllexport)
    #  pragma message ("Globale Variablen werden exportiert")
    #elif defined DLL_IMP
    #  define BASICPOS_DECL __declspec(dllimport)
    #  pragma message ("Globale Variablen werden importiert")
    #endif
    
    IncludeFile message.h:
    #include <stdio.h>
    #include <string.h>
    
    #ifndef MESSAGE_H 
    #define MESSAGE_H
    
    #pragma warning(disable : 4100)
    #pragma warning(disable : 4189)
    
    class BASICPOS_DECL Message
    {
      public:
    
      enum msgName { ILLEGAL_MSG=0, KOORD_MSG, END_MSG};
    
    //  private:
      protected:
    	  Message::msgName id;
    
      protected:
        Message (msgName _id)
        : id(_id) {};
    
        Message (const Message &msg)
        : id(msg.id) {};
    
        Message & operator=(const Message &) {
    		return *this;
    	}
    
      public:
    
        inline Message::msgName GetMessageId(void) const {
           return id;
        }
        inline virtual size_t SizeOf(void) const =0;
        inline virtual size_t DataSize(void) const =0;
        inline virtual int GetValue(int sizeOf, void *pVal) =0;
        inline virtual Message *Clone(void) const =0;
        inline virtual int NameToAscii(char *pName, int maxLen) =0;
        inline virtual const char * NameToAscii(void) const =0;
        inline virtual ~Message(void) {
        };
    };
    #endif
    
    IncludeFile koordMsg.h:
    class BASICPOS_DECL KoordMsgData {
      private:
    	int startX, startY, sizeX, sizeY; 
    
      public:
    
        KoordMsgData ()
    	: startX (0), 
    	  startY (0), 
    	  sizeX  (0), 
    	  sizeY  (0) 
    	{}
    
        KoordMsgData (int _startX, int _startY, int _sizeX, int _sizeY)
    	: startX (_startX), 
    	  startY (_startY), 
    	  sizeX  (_sizeX), 
    	  sizeY  (_sizeY) 
    	{}
    
        KoordMsgData (const KoordMsgData &attrMsgData)
    	: startX (attrMsgData.startX), 
    	  startY (attrMsgData.startY), 
    	  sizeX  (attrMsgData.sizeY), 
    	  sizeY  (attrMsgData.sizeX) 
        {};
    
        int GetStartX() { return startX;};
        int GetStartY() { return startY;};
        int GetSizeX() { return sizeX;};
        int GetSizeY() { return sizeY;};
    
        void SetStartX(int x) { startX = x;};
        void SetStartY(int y) { startY = y;};
        void SetSizeX(int x) { sizeX = x;};
        void SetSizeY(int y) { sizeY = y;};
    };
    
    class BASICPOS_DECL KoordMsg: public Message {
    
      public:
        KoordMsg();
    
        KoordMsg( int _startX, int _startY, int _sizeX, int _sizeY);
    	KoordMsg( const KoordMsg &koordMsg ); 
    
        size_t SizeOf(void) const;
    
        size_t DataSize(void) const;
    
    	void SetStartX (int startX);
    	void SetStartY (int startY);
    	void SetSizeX (int sizeX);
    	void SetSizeY (int sizeY);
    
    	int GetValue(int sizeOf, void *pVal);
    
    	int GetStartX(void);
    	int GetStartY(void);
    	int GetSizeX(void);
    	int GetSizeY(void);
    
    	Message * MsgInBuffer(void *pB);
    
        Message * Clone(void) const;
    
        const char * NameToAscii(void) const
        {
           return "KoordMsg";
        }
    
    	virtual int NameToAscii(char *pStr, int maxLen);
    
    	virtual ~KoordMsg(void);
    
      private:
    	KoordMsgData koordMsgData;
    };
    
    File koordMsg.cpp:
    #define _CRT_SECURE_NO_DEPRECATE
    
    #include <string.h>
    
    #define DLL_EXP
    #include "../../userlib/include/define.h"
    #include "../include/message.h"
    #include "../include/koordMsg.h"
    #undef DLL_EXP
    
    #include <new>
    
    KoordMsg::KoordMsg()
    : Message( Message::KOORD_MSG ),
      koordMsgData (0, 0, 0, 0)
    {}
    
    KoordMsg::KoordMsg( int _startX, int _startY, int _sizeX, int _sizeY)
    : Message( Message::KOORD_MSG ),
      koordMsgData (_startX, _startY, _sizeX, _sizeY)
    {}
    	// Kopierkonstruktor
    KoordMsg::KoordMsg( const KoordMsg &koord ) 
    : Message( Message::KOORD_MSG ),
      koordMsgData (koord.koordMsgData)
    {}
    
    size_t KoordMsg::SizeOf(void) const {
        return sizeof (*this);
    }
    
    size_t KoordMsg::DataSize(void) const {
        return sizeof koordMsgData;
    }
    
    int KoordMsg::GetValue(int sizeOf, void *pVal)
    {
       int retCode(0);
       if (sizeOf == sizeof KoordMsgData) {
          *((KoordMsgData *)pVal) = koordMsgData;
    //    alternativ:
    //    memcpy((KoordMsgData *)pVal, &koordMsgData, sizeof KoordMsgData);
          retCode = 1;
       }
       return retCode;
    }
    
    Message * KoordMsg::Clone(void) const
    {
       return new KoordMsg(*this);
    }
    
    int KoordMsg::NameToAscii(char *pStr, int maxLen)
    {
       _snprintf (pStr, maxLen, "%s startX=%d startY=%d sizeX=%d sizeY=%d",NameToAscii(),GetStartX(), GetStartY(), GetSizeX(), GetSizeY());
       pStr[maxLen-1] = 0;
       return 1;
    }
    
    void KoordMsg::SetStartX (int x)
    {
       koordMsgData.SetStartX(x);
    }
    
    void KoordMsg::SetStartY (int y)
    {
       koordMsgData.SetStartX(y);
    }
    
    void KoordMsg::SetSizeX (int x)
    {
       koordMsgData.SetSizeX(x);
    }
    
    void KoordMsg::SetSizeY (int y)
    {
       koordMsgData.SetSizeY(y);
    }
    int KoordMsg::GetStartX(void) {return koordMsgData.GetStartX();}
    int KoordMsg::GetStartY(void) {return koordMsgData.GetStartY();}
    int KoordMsg::GetSizeX(void)  {return koordMsgData.GetSizeX();}
    int KoordMsg::GetSizeY(void)  {return koordMsgData.GetSizeY();}
    
    KoordMsg::~KoordMsg(void) {
    }
    
    File startUp.cpp
    
    #include <stdio.h>
    #include <windows.h>
    #include <exception>
    
    #include <sys/stat.h>
    #include <new>
    
    #define DLL_IMP
    #include "../../../userlib/include/define.h"
    int CreateNewProcess (
    					   // Auszuführender Programmcode
    					 const char *pExe, 
    					   // Prozess-Info
    					 PROCESS_INFORMATION *ppi);
    
    #include "../../../userlib/include/message.h"
    #include "../../../userlib/include/koordMsg.h"
    
    extern "C" BASICPOS_DECL void * GetBaseAddr(void);
    #undef DLL_IMP
    
    #define DLL_EXP
    #include "../../../userlib/include/define.h"
    #undef DLL_EXP
    
    int main ()
    {
    	HANDLE procHdl[10];
        int nProc(0), quittCreateProcess(0);
    
    	try {
    
           void (*pBaseAddr) (GetBaseAddr());
    
           KoordMsg koordMsg(1,2,3,4);
           Message (*pMessage) (new (pBaseAddr) KoordMsg(koordMsg));
           size_t SizeOf    (pMessage->SizeOf());
           size_t dataSize  (pMessage->DataSize());
           int    koordData (pMessage->GetValue(dataSize, &koordMsg));
    
           fprintf (stdout, "\nTextEditProcess starten.\n");
    
           const char *pDirTextEdit = "..\\textEdit\\Debug";
           const char *pExeTextEdit = "..\\textEdit\\Debug\\textEdit.exe";
    
               // Das Verzeichnis für das zu startende Anwenderprogramm muß existieren.
            struct stat dirStatus;
            dirStatus.st_mode=0;
     	    int dirInfo (stat(pDirTextEdit, &dirStatus));
    	    if (dirInfo!=0 || (dirStatus.st_mode & S_IFDIR)==0) {
               fprintf (stdout, "\nDas Verzeichnis %s konnte nicht geöffnet werden.\n");
    		   Sleep (10000);
    		   return (0);
            }
                // Das Anwenderprogramm muß existieren und muß ausführbar sein.
            struct stat fileStatus;
    	    fileStatus.st_mode=0;
    	    int fileInfo (stat(pExeTextEdit, &fileStatus));
    
    	    if (fileInfo!=0 || (fileStatus.st_mode & S_IEXEC)==0) {
               fprintf (stdout, "Start des Programm %s nicht möglich.\n", pExeTextEdit);
    		   Sleep (10000);
    		   return (0);
            }
    
            PROCESS_INFORMATION textEditProcessInfo;
            memset( &textEditProcessInfo, 0, sizeof (PROCESS_INFORMATION) );
    
            quittCreateProcess = CreateNewProcess (pExeTextEdit, &textEditProcessInfo);
            if (quittCreateProcess != 1) {
               fprintf (stdout, "CreateNewProcess textEdit.exe war nicht erfolgreich\n");
    		   Sleep (10000);
    		   return (0);
    	    }
    
    	    procHdl[nProc] = textEditProcessInfo.hProcess;
    	    ++nProc;
    
            int index(0);
    
              // Nachfolgend alle Ausgaben von DebugPrint::Print(..) nach stdout
            fprintf (stdout, "\nAuf das Ende des Client-Prozess warten\n\n");
            DWORD lastErr(0);
            DWORD dwRet ( WaitForMultipleObjects(nProc, procHdl, TRUE, INFINITE) );
            switch ( dwRet ) {
    	       case WAIT_FAILED: {
                  fprintf (stdout, "\n\nIn StartUp: Nach WaitForSingleObject:WAIT_FAILED\n");
                  lastErr = GetLastError();
                  fprintf (stdout, "\n\nNach GetLastError() = %ld\n", lastErr);
                  Sleep (10000);
    		   }
    	       break;
    
    	       case WAIT_OBJECT_0:
                  fprintf (stdout, "\n\n Nach WaitForSingleObject:WAIT_OBJECT_0\n");
                  Sleep (10000);
               break;
    
    	       case WAIT_TIMEOUT:
                  fprintf (stdout, "\n\nNach WaitForSingleObject:WAIT_TIMEOUT\n");
                  Sleep (10000);
               break;
    
    	       default:
                  fprintf (stdout, "\n\nNach WaitForSingleObject:default\n");
                  Sleep (10000);
               break;
    	    }
        }
    
    	catch (...)
    	{
           fprintf (stdout, "\n\nIn StartUp main(): unhandelt exception, Programm wird beendet. GetLastError() = %ld\n\n", GetLastError());
           Sleep (10000);
    	}
    
        return 0;
    }
    
    int CreateNewProcess(
    					   // Auszuführender Programmcode
    					 const char *pExe, 
    					   // Prozess-Info
    					 PROCESS_INFORMATION *ppi)
    {
        int retCode(0);
        STARTUPINFO si; // = {0};
    	memset( &si, 0, sizeof(si) );
        si.cb = sizeof( STARTUPINFO );
    
        if (pExe) { 
           DWORD fdwCreate = CREATE_NEW_CONSOLE;
           BOOL retCreateProcess ( CreateProcess( pExe, "", NULL, NULL, TRUE, fdwCreate, NULL, NULL, &si, ppi ) );
    
    	   if(retCreateProcess != 0 && ppi->hProcess)
              retCode = 1;
    	}
        return retCode;
    }
    
    File textEdit.cpp:
    #include "../../../userlib/include/message.h"
    #include "../../../userlib/include/koordMsg.h"
    
    #undef DLL_IMP
    
    int main ()
    {
       try {
    
    	  Message (*pMessage) ((Message *)GetBaseAddr());
          KoordMsg koordMsg;
    
          size_t SizeOf    (pMessage->SizeOf());
          size_t dataSize  (pMessage->DataSize());
          int koordData    (pMessage->GetValue(dataSize, &koordMsg));
       }
    
       catch (...) {
           fprintf (stdout, "\n\nIn TextEdit main(): unhandelt exception, Programm wird beendet. GetLastError() = %ld\n\n", GetLastError());
           Sleep (10000);
       }
       Sleep (10000);
       return 0;
    }
    


  • Hans500 schrieb:

    Probleme bei Aufruf virtueller Funktionen von Objekten, die im prozessübergreifenden globalen Speicher angelegt sind.

    Kein Wunder. Das geht schlicht und ergreifend nicht. Zumindest nicht ohne gröbere Hacks/Workarounds die sich auf undokumentierte nicht portable Interna eines Compilers/OS/... verlassen.

    Hans500 schrieb:

    Innerhalb von startUp.exe können die Funktionen der Klasse KoordMsg problemlos aufgerufen werden:

    Japp. Weil der VTable Zeiger für den Prozess der das Objekt erzeugt hat natürlich passt.

    Hans500 schrieb:

    Wenn jetzt in main() des Client-Prozess textEdit.exe die virtuellen Funktionen der Basisklasse Message aufgerufen werden kommt es zum Absturz:

    Auch klar, weil dort die Adressen eben nicht mehr passen.

    Hans500 schrieb:

    Meine Frage: Was mache ich falsch?

    Du versuchst was zu machen was so einfach nicht geht.

    Hans500 schrieb:

    Muß ich zusätzlich eine Compiler-Option setzen?

    Ne, da wird so nix draus werden, ganz egal welche Optionen du irgendwo setzt.



  • @hustbaer: Mit Windows XP und Visual cpp 6.0 32 Bit ging es noch,
    aber nur dann, wenn man in WinMain(...) anstatt
    pfileView = MapViewOfFile (fileMappingHdl, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    die Funktion
    pfileView = MapViewOfFileEx (fileMappingHdl, FILE_MAP_ALL_ACCESS, 0, 0, 0, (LPVOID)GLOBMEMBASEADDRESSE);
    aufruft.



  • Mag sein dass es ging.
    Aber du verlässt dich dabei auf viele Dinge die nicht garantiert sind, und oft sogar nichtmal dokumentiert.

    Möglicherweise bekommt man es sogar unter Windows 7...10 wieder zum Laufen, indem man sich ne "passende" Base-Address sucht.

    Gibt aber echt viele Dinge die da reinstören können. Ich würde mich nicht auf so einen Hack verlassen wollen.



  • @hustbear:
    Ich habe mich beim Aufruf der WinAPI-Funktionen CreateFileMapping(...) bzw. OpenFileMapping(...) und MapViewOfFile (...) exakt nach den Vorgaben aus der Mikrosoft-Dokumentation gehalten.
    Dort wird nirgendwo darauf hingewiesen, daß Mikroft da Probleme mit virtuellen Funktionen hat.

    Insgesamt ist das wirklich äußerst schwach von Mikrosoft.

    Mir bleibt wohl nix anderes übrig als auf LINUX umzusteigen.

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v=vs.85).aspx

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa366791(v=vs.85).aspx

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa366763(v=vs.85).aspx



  • Und Linux zaubert jetzt oder wie?
    Wenn du es wirklich durchziehen möchtest: MSVC bietet eine bestimmte Direktive, die VTable direkt im Objekt selbst zu speicher.



  • [quote="Techel"]Und Linux zaubert jetzt oder wie?
    Wenn du es wirklich durchziehen möchtest: MSVC bietet eine bestimmte Direktive, die VTable direkt im Objekt selbst zu speicher.[/quote]
    Wie könnte das aussehen?
    Könntest du mir ein Beispiel geben?



  • Oh, hab da was verwechselt, das geht doch nicht wie geplant. Du müsstest dann wohl auf ein C-Interface umsteigen, zB. eine Struktur aufbauen, welche Funktionszeiger, wie bei virtuellen Funktion, enthält. Auch hier gilt, dass beide Programme komplett gleich sind bzw die gleiche Codesektion haben.



  • Techel schrieb:

    Auch hier gilt, dass beide Programme komplett gleich sind bzw die gleiche Codesektion haben.

    Wenn das schon gegeben ist, dann geht es auch mit ganz normalem Vtable.



  • Hans500 schrieb:

    @hustbear:
    Ich habe mich beim Aufruf der WinAPI-Funktionen CreateFileMapping(...) bzw. OpenFileMapping(...) und MapViewOfFile (...) exakt nach den Vorgaben aus der Mikrosoft-Dokumentation gehalten.
    Dort wird nirgendwo darauf hingewiesen, daß Mikroft da Probleme mit virtuellen Funktionen hat.

    Insgesamt ist das wirklich äußerst schwach von Mikrosoft.

    Nein, da ist gar nix schwach von Microsoft. Es bezeugt nur dass dir das Verständnis fehl, dafür was man mit C++ machen kann und was nicht.
    Der C++ Standard weiss einfach nichts von Prozessen und schon gar nicht von "shared memory".
    Da muss überhaupt gar nichts funktionieren.
    Nächstens versucht du noch ein Speicherabbild eines Objekts in ein File zu schreiben, dann in einem wildfremden Prozess reinzuladen und es hat dann gefälligst zu funktionieren.
    Wird es aber nicht.

    Hans500 schrieb:

    Mir bleibt wohl nix anderes übrig als auf LINUX umzusteigen.

    OK, wenn du meinst.



  • hustbaer schrieb:

    Techel schrieb:

    Auch hier gilt, dass beide Programme komplett gleich sind bzw die gleiche Codesektion haben.

    Wenn das schon gegeben ist, dann geht es auch mit ganz normalem Vtable.

    Jaja, da sieht man den Wald vor lauter Bäumen nicht.



  • Und wozu das ganze? Wenn du irgendeinen IPC Mechanismus implementieren willst, gibts doch quasi unendlich viele Möglichkeiten, auch viele einfachere.



  • Hallo,

    der Unterschied zwischen XP und 7, 8, ... wird hier wohl ASLR sein. Das sorgt dafür, dass die Images nicht immer an derselben Startadresse geladen werden, was dazu führt, dass die Methodenpointer von DLL Code, der über Prozess 1 geladen wird nicht an derselben Stelle zu liegen kommen wie beim nächsten Prozess, der die DLL lädt.
    Das ist ein Sicherheitsfeature und gibt es _auch_ unter aktuellen Linuxen 😃

    Könnte man theoretisch ausschalten (global über Registry/Wahnsinn, lokal über Linkereinstellung/auch keine gute Idee).

    Offensichtlich versuchst Du hier IPC. Kann man schon über gesharte Daten in MMFs machen (Zugriff korrekt synchronisieren!) - aber ich würde hier dringend raten, Daten und Code zu trennen.

    Matthias



  • Auch ohne ASLR ist es Zufall.



  • Matthias G. schrieb:

    ... wird hier wohl ASLR sein. ...
    Das ist ein Sicherheitsfeature und gibt es _auch_ unter aktuellen Linuxen 😃

    Bei FreeBSD scheint Shared-Memory nicht mit ASLR geschützt zu sein. Auch in der aktuellsten Version nicht ...

    https://wiki.freebsd.org/AddressSpaceLayoutRandomization



  • @Matthias G., Mechanics, merano:
    ASLR kann man in in visual cpp 2010 mit der Linkeroption /DYNAMICBASE:NO und mit /FIXED abschalten.
    Trotzdem tritt der Fehler bei Windows 7 Professional, 64 Bit, Service Pack 1
    noch auf.

    Hier der Programmcode

    Prozess 1:
    --------------

    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    #include <new>
    #include <sys/stat.h>
    #include "..\..\include\classA.h"

    #include <new>

    int main()
    {
    DWORD lastError (0);

    HANDLE mapFileHdl (CreateFileMapping(
    INVALID_HANDLE_VALUE, // use paging file
    NULL, // default security
    PAGE_EXECUTE_READWRITE, // read/write/execute access
    0, // maximum object size
    sizeof A1, // maximum object size
    mappingFileName)); // name of mapping object

    if (mapFileHdl == NULL)
    {
    lastError = GetLastError();
    printf("CreateFileMapping(...) war nicht erfolgreich, GetLastError() = (%d).\n", lastError);

    return 1;
    }

    # ifdef FIXEDMAPPING
    void (*pBuffer) (MapViewOfFileEx (mapFileHdl, FILE_MAP_ALL_ACCESS,
    0, 0, 0, (void *)GLOBMEMBASEADDRESSE));
    # else
    void (*pBuffer) (MapViewOfFile (mapFileHdl, FILE_MAP_ALL_ACCESS,
    0, 0, 0));
    # endif

    if (pBuffer == NULL)
    {
    lastError = GetLastError();
    printf("MapViewOfFile(...) war nicht erfolgreich, GetLastError() = (%d).\n", lastError);

    CloseHandle(mapFileHdl);

    return 1;
    }

    A1 a1;
    A0 (*pA00)(&a1);
    pA00->SetId(1);

    memset (pBuffer, 0x99, sizeof (A1));
    *(void **) pBuffer = 0L;
    A0 (*pA0) (new (pBuffer) A1(&a1));
    pA0->SetId(-1);
    __int64 id (pA0->GetId());

    A1 xx,yy,zz;

    int c (_getch());

    UnmapViewOfFile(pBuffer);

    CloseHandle(mapFileHdl);

    return 0;
    }

    Prozess 2:
    --------------

    #include <windows.h>
    #include <stdio.h>
    #include "..\..\include\classA.h"

    int main()
    {
    DWORD lastError(0);

    HANDLE mapFileHdl (OpenFileMapping(
    FILE_MAP_ALL_ACCESS, // read/write access
    FALSE, // do not inherit the name
    mappingFileName)); // name of mapping object

    if (mapFileHdl == NULL)
    {
    lastError = GetLastError();
    printf("OpenFileMapping(...) war nicht erfolgreich, GetLastError() = (%d).\n", lastError);

    return 1;
    }

    # ifdef FIXEDMAPPING
    void (*pBuffer) (MapViewOfFileEx (mapFileHdl, FILE_MAP_ALL_ACCESS,
    0, 0, 0, (void *)GLOBMEMBASEADDRESSE));
    # else
    void (*pBuffer) (MapViewOfFile (mapFileHdl, FILE_MAP_ALL_ACCESS,
    0, 0, 0));
    # endif

    if (pBuffer == NULL)
    {
    lastError = GetLastError();
    printf("MapViewOfFile(...) war nicht erfolgreich, GetLastError() = (%d).\n", lastError);

    CloseHandle(mapFileHdl);

    return 1;
    }

    A0 (*pA0) ((A0 😉 (pBuffer));
    __int64 id0 (pA0->GetId());

    UnmapViewOfFile(pBuffer);

    CloseHandle(mappingFileName);

    return 0;

    gemeinsames Includefile classA.h:
    ------------------------

    //#define FIXEDMAPPING
    #define GLOBMEMBASEADDRESSE 0x52000000

    char mappingFileName[]=("mappingFileName");

    class A0
    {
    public:
    A0() {}
    virtual __int64 GetId() = 0;
    virtual void SetId(__int64 i) = 0;
    };

    class A1 : public A0
    {
    private:
    __int64 i;
    public:
    A1()
    :A0(),
    i(0)
    {
    };

    A1(A1 *pa)
    :A0(),
    i(pa->i)
    {
    };

    A1(A1 &ra)
    :A0(),
    i(ra.i)
    {
    };

    void SetId(__int64 id)
    {
    i = id;
    }
    __int64 GetId()
    {
    return i;
    }
    };


Anmelden zum Antworten