Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. DLL memory issue

DLL memory issue

Scheduled Pinned Locked Moved C / C++ / MFC
7 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Andrew Hoole
    wrote on last edited by
    #1

    Hi I have been trying to write a dialog dll and have been having some real issues with it see (DLL and CTypedPrtList problem[^]). It seems to have moved away from my initial concerns of using CTypedPtrList in the DLL to a more general issue hence the new post. I stripped the code down to the bare minimum removing all the interesting stuff and it still fails if I OK out of the dialog but not if I Cancel. To recap on the application. void CTestApp::OnFileOpen() { CLantisPatientSelectDlg dlg; if(dlg.DoModal() == IDOK){ m_nPatID1 = dlg.GetPatID1(); } } CLantisPatientSelectDlg is implemented in the DLL with exported constructors, DoModal() and GetPatID1() member functions. void CLantisPatientSelectDlg::OnOK() { int nIndex; CPatientDetails *pPatientDetails; CListCtrl *pList = (CListCtrl *)GetDlgItem(IDC_PATIENTLIST); nIndex = pList->GetSelectionMark(); if(nIndex != -1){ // Do something interesting } else { m_nSelectedPatID1 = -1; } // Get any background list loading to terminate m_bTerminateLoad = true; ::WaitForSingleObject(m_hListLoadingThread,INFINITE); CDialog::OnOK(); } void CLantisPatientSelectDlg::OnCancel() { // Get any background list loading to terminate m_bTerminateLoad = true; ::WaitForSingleObject(m_hListLoadingThread,INFINITE); CDialog::OnCancel(); } Now I have done some debugging on this and it appears that when the program goes through the OnOK() function the line m_nSelectedPatID1 = -1; corrupts the "this" pointer of the CTestApp class such that when I get back into the OnFileOpen() function the m_nPatID1 = dlg.GetPatID1(); fails. Looking at the memory allocation somehow the m_nSelectedPatID1 variable and the "this" pointer are using the same memory and hence setting the variable to -1 in the DLL gives a pointer which is nonsense. Now why is this happening? I am using two header files for the CLantisPatientSelectDlg. One for build the DLL which needs to know about all the internal stuff and another for building the application which only has the exported functions in it. Reasoning being that the users don't need to know all that internal stuff

    L 1 Reply Last reply
    0
    • A Andrew Hoole

      Hi I have been trying to write a dialog dll and have been having some real issues with it see (DLL and CTypedPrtList problem[^]). It seems to have moved away from my initial concerns of using CTypedPtrList in the DLL to a more general issue hence the new post. I stripped the code down to the bare minimum removing all the interesting stuff and it still fails if I OK out of the dialog but not if I Cancel. To recap on the application. void CTestApp::OnFileOpen() { CLantisPatientSelectDlg dlg; if(dlg.DoModal() == IDOK){ m_nPatID1 = dlg.GetPatID1(); } } CLantisPatientSelectDlg is implemented in the DLL with exported constructors, DoModal() and GetPatID1() member functions. void CLantisPatientSelectDlg::OnOK() { int nIndex; CPatientDetails *pPatientDetails; CListCtrl *pList = (CListCtrl *)GetDlgItem(IDC_PATIENTLIST); nIndex = pList->GetSelectionMark(); if(nIndex != -1){ // Do something interesting } else { m_nSelectedPatID1 = -1; } // Get any background list loading to terminate m_bTerminateLoad = true; ::WaitForSingleObject(m_hListLoadingThread,INFINITE); CDialog::OnOK(); } void CLantisPatientSelectDlg::OnCancel() { // Get any background list loading to terminate m_bTerminateLoad = true; ::WaitForSingleObject(m_hListLoadingThread,INFINITE); CDialog::OnCancel(); } Now I have done some debugging on this and it appears that when the program goes through the OnOK() function the line m_nSelectedPatID1 = -1; corrupts the "this" pointer of the CTestApp class such that when I get back into the OnFileOpen() function the m_nPatID1 = dlg.GetPatID1(); fails. Looking at the memory allocation somehow the m_nSelectedPatID1 variable and the "this" pointer are using the same memory and hence setting the variable to -1 in the DLL gives a pointer which is nonsense. Now why is this happening? I am using two header files for the CLantisPatientSelectDlg. One for build the DLL which needs to know about all the internal stuff and another for building the application which only has the exported functions in it. Reasoning being that the users don't need to know all that internal stuff

      L Offline
      L Offline
      lynchspawn
      wrote on last edited by
      #2

      Ah - I see what happened now. I ran into the same problem years ago. I wasn't intentionally using different headers but by mistake ended up doing something very similar. I'm sure someone else can give you a more detailed explanation of this but the short story is that the address of your ID is off into a bogus area due to the multiple header files. I think if you really need to be able to do this, you need to setup some dummy variables so that both of the headers represent a class with the same layout/size. I'm still not sure if it is going to work in that case but I do know from experience that using multiple headers holding different variables will cause big problems. Sorry I can't give more/better info.

      A 1 Reply Last reply
      0
      • L lynchspawn

        Ah - I see what happened now. I ran into the same problem years ago. I wasn't intentionally using different headers but by mistake ended up doing something very similar. I'm sure someone else can give you a more detailed explanation of this but the short story is that the address of your ID is off into a bogus area due to the multiple header files. I think if you really need to be able to do this, you need to setup some dummy variables so that both of the headers represent a class with the same layout/size. I'm still not sure if it is going to work in that case but I do know from experience that using multiple headers holding different variables will cause big problems. Sorry I can't give more/better info.

        A Offline
        A Offline
        Andrew Hoole
        wrote on last edited by
        #3

        Yeah I think I am going to have to use the same header file but when I tried it earlier I get compiler errors on the // Dialog Data //{{AFX_DATA(CLantisPatientSelectDlg) enum { IDD = IDD_SELECTPATDLG }; // NOTE: the ClassWizard will add data members here //}}AFX_DATA section of the header because that is declared in the resource.h file of the dll and not the resource.h file of the application. Is it a problem if several of these IDs resolve to the same number? I would have thought that the layout/size of the class would have been held in one of the compiled files that are used by the linker so something.

        A 1 Reply Last reply
        0
        • A Andrew Hoole

          Yeah I think I am going to have to use the same header file but when I tried it earlier I get compiler errors on the // Dialog Data //{{AFX_DATA(CLantisPatientSelectDlg) enum { IDD = IDD_SELECTPATDLG }; // NOTE: the ClassWizard will add data members here //}}AFX_DATA section of the header because that is declared in the resource.h file of the dll and not the resource.h file of the application. Is it a problem if several of these IDs resolve to the same number? I would have thought that the layout/size of the class would have been held in one of the compiled files that are used by the linker so something.

          A Offline
          A Offline
          Andrew Hoole
          wrote on last edited by
          #4

          Ok I have now included the resource.h file in the CLantisPatientSelectDlg.h file and now the whole thing(including the important bits I had removed for debugging purposes) compiles and runs fine. So now I just need to find out how I can use different header files without getting this trouble as it seems the only way to hide from the user all the mess of the implementation. Thanks for all the help and comments so far. Andrew Hoole

          B 1 Reply Last reply
          0
          • A Andrew Hoole

            Ok I have now included the resource.h file in the CLantisPatientSelectDlg.h file and now the whole thing(including the important bits I had removed for debugging purposes) compiles and runs fine. So now I just need to find out how I can use different header files without getting this trouble as it seems the only way to hide from the user all the mess of the implementation. Thanks for all the help and comments so far. Andrew Hoole

            B Offline
            B Offline
            Blake Miller
            wrote on last edited by
            #5

            How to hide mess from user: 1. Implement a data structure that has the data you need to and from the dialog. Share this data structure in a header between the main program and the support DLL. Program passes pointer to valid memory block representing data structure to exported DLL function. 2. Also pass HWND of parent window into exported function. This way, your C++ object does not have to cross the DLL boundary. Wihtin the DLL you cna make a temporary CWnd and 'attach' the passed in HWnd to it. Remember to Detach ont he way out. Now you don't have to 'expose' any more details than necessary and almost all, if not all, of your problems are solved. The advantage here, is you can actually make your entire MFC Dialog DLL code compatible with a regular Win32 program if done correctly - static link MFC, use the proper AFX macros, etc. Trying to export a 'fraction' of a dialog's class from the DLL will only get you into more trouble than it is worth. You are not ending up with the proper offsets to member variables, virtual functions, etc. I would stay clear of any 'cute' skinning or other 'framework' system that relies on such a method.

            A 1 Reply Last reply
            0
            • B Blake Miller

              How to hide mess from user: 1. Implement a data structure that has the data you need to and from the dialog. Share this data structure in a header between the main program and the support DLL. Program passes pointer to valid memory block representing data structure to exported DLL function. 2. Also pass HWND of parent window into exported function. This way, your C++ object does not have to cross the DLL boundary. Wihtin the DLL you cna make a temporary CWnd and 'attach' the passed in HWnd to it. Remember to Detach ont he way out. Now you don't have to 'expose' any more details than necessary and almost all, if not all, of your problems are solved. The advantage here, is you can actually make your entire MFC Dialog DLL code compatible with a regular Win32 program if done correctly - static link MFC, use the proper AFX macros, etc. Trying to export a 'fraction' of a dialog's class from the DLL will only get you into more trouble than it is worth. You are not ending up with the proper offsets to member variables, virtual functions, etc. I would stay clear of any 'cute' skinning or other 'framework' system that relies on such a method.

              A Offline
              A Offline
              Andrew Hoole
              wrote on last edited by
              #6

              Are you saying that I should wrap my DLL dialog class in another class with a simple interface. Otherwise I can't see how what you are suggesting gets me away from having to have the header file of my DLL dialog exposed to the users. Using the HWND idea - would that mean I don't create a direct instance of the DLL dialog class as I have done but rather pass the HWND into a simple function which then attachs to it and creates the dialog class internally. Sorry I am not being very bright here but thanks for the help.

              B 1 Reply Last reply
              0
              • A Andrew Hoole

                Are you saying that I should wrap my DLL dialog class in another class with a simple interface. Otherwise I can't see how what you are suggesting gets me away from having to have the header file of my DLL dialog exposed to the users. Using the HWND idea - would that mean I don't create a direct instance of the DLL dialog class as I have done but rather pass the HWND into a simple function which then attachs to it and creates the dialog class internally. Sorry I am not being very bright here but thanks for the help.

                B Offline
                B Offline
                Blake Miller
                wrote on last edited by
                #7

                Sorry, option 2 is the one I meant. When you pass in the HWND of the 'parent' window to the function, you attach this passed HWND to an internal CWnd object, and that CWnd can be the 'parent' for your internal dialog class. After DoModal returns and you collected up all the data, you can detach the temporary CWnd from the passed HWND. This way, the entire interface into the DLL to 'call' the dialog is a pointer to your data structure and an HWND. You only need to give the user a header file with the definition of your data structure and a function prototpye - the function exported from your DLL. I do this all the time to get InstallShield or legacy Win32 applications to be able to call MFC dialogs.

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups