access violation executing in CLR host application

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

access violation executing in CLR host application

Post by Alan Stewart »

Baffled at this point after struggling for a few days.

wxWidgets 3.0.4, in the form of a pre-built VS 2010 64-bit DLL, debug build.
Windows 7 Pro, VS 2017.

This is my first time developing in CLR, so I may be making a rookie mistake.
The DLL is one we use successfully in other projects, but as far as I know this is the first usage within a CLR host application.

The main VS 2017 C#/CLR DLL project implements a plugin to the CLR host application. It calls into:
A new VS210 C++/CLI DLL project, implementing a CLR interface, a middle man which calls into:
A legacy VS2010 C++ DLL project, a collection of legacy wxWidgets dialogs, which calls into:
The pre-built wxWidgets DLL mentioned above.

I've already successfully displayed the first simple wxWidgets dialog in the collection. I've run into a road block with the second, much more complex dialog. The interface to this dialog is implemented as a series of functions. Static variables are used to store wx application and dialog state information. There is a creation function, a display function, a destruction function, and a bunch of getter and setter functions for interacting with the dialog state. My problem is in the creation function, ConfigCreate(), which emits the errors below in the Output window. (Uiwrapper.dll is the C++/CLI project.)

Exception thrown: 'System.AccessViolationException' in uiwrapper.dll
An unhandled exception of type 'System.AccessViolationException' occurred in uiwrapper.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

The debugger dialog error is:

Exception thrown at 0x0000000000000000 in ArcGISPro.exe: 0xC0000005: Access violation executing location 0x0000000000000000.

This occurs before the body of the legacy ExportConfigDlg constructor begins execution, which suggests it is occurring within the wxPropertySheetDialog constructor, but I have not been able to get the debugger to step into that. It is implemented in wx/generic/propdlg.h.

This is how ConfigCreate() is being called from the C++/CLI project. To simplify things, instead of passing the HWND from a host application window, I'm passing the desktop window:

Code: Select all

bool ok = ConfigCreate(GetDesktopWindow());
The ConfigCreate() code:

Code: Select all

bool DECLSPEC ConfigCreate(HWND hWnd)
{
  if ((::root) || (::config))                                                                                                       // test static variables
    return false;

  bool retval = wxEntryStart(GetModuleHandle(NULL), NULL, NULL, SW_SHOWNORMAL);
  if ((retval) && (wxTheApp))
  {
    ::root = new guikit::ModalRoot((WXHWND)hWnd);                                                                 // ModalRoot tracks the parent
    if (!::root)
      return false;

    wxTheApp->SetTopWindow(hWnd ? static_cast<wxWindow*>(*root) : (wxWindow*)NULL);

    ::config = new ExportConfigDlg((wxWindow*) *root, _wc("Export Configuration"));                  // *** exception occurs within this constructor ***
    if (!::config)
    {
      delete ::root;
      ::root = 0;
      return false;
    }
  }
  else
  {
    return false;
  }

  return true;
}
The ExportConfigDlg constructor:

Code: Select all

ExportConfigDlg::ExportConfigDlg(wxWindow* parent, const wxString& title) :
      wxPropertySheetDialog(parent,
                            wxID_ANY,
                            title,
                            parent->GetPosition(),
                            parent->GetSize(),
                            wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
      exportPage_(0),
      layerPage_(0),
      attribPage_(0),
      linkPage_(0),
      shiftPage_(0),
      notebook_(0)
    {                                                                                                                              // *** exception occurs here ***
      notebook_ = dynamic_cast<wxNotebook*>(GetBookCtrl());

      exportPage_ = new ExportPage(notebook_);
      layerPage_ = new LayerPage(notebook_);
      attribPage_ = new AttribPage(notebook_);
      linkPage_ = new LinkPage(notebook_);
      shiftPage_ = new ShiftPage(notebook_);
    }
All thoughts and suggestions are welcome!

TIA,
Alan
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

Re: access violation executing in CLR host application

Post by Alan Stewart »

Oops, just discovered one misconception. I thought the first dialog I have implemented was a wxWidgets dialog, but after auditing the code I was wrong. It is an instance of CDialog. So the problem export configuration dialog is my first attempt at using wxWidgets in this environment.
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

Re: access violation executing in CLR host application

Post by Alan Stewart »

Some progress. I discovered the PDB for the wxWidgets DLL was not being copied from the repository to the correct location. #-o That's why I could not step into that DLL. I can now and have narrowed down the exception location to wxDialogBase::GetParentForModalDialog() in src/common/dlgcmn.cpp. Specifically:

Code: Select all

    if ( !parent )
        parent = CheckIfCanBeUsedAsParent(wxTheApp->GetTopWindow());
GetTopWindow() appears to return a valid value, but when I attempt to debug into this final call to CheckIfCanBeUsedAsParent() the exception is immediately thrown.

???
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: access violation executing in CLR host application

Post by doublemax »

Code: Select all

::root = new guikit::ModalRoot((WXHWND)hWnd); // ModalRoot tracks the parent
    if (!::root)
      return false;

    wxTheApp->SetTopWindow(hWnd ? static_cast<wxWindow*>(*root) : (wxWindow*)NULL);

    ::config = new ExportConfigDlg((wxWindow*) *root, _wc("Export Configuration"));        
This looks a little fishy. What exactly does guikit::ModalRoot do and what does it return? You can only use a wxWindow* for SetTopWindow and as parent for the dialog.
Use the source, Luke!
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

Re: access violation executing in CLR host application

Post by Alan Stewart »

ModalRoot wraps a wxWindows pointer:

Code: Select all

// definition of ::root

guikit::ModalRoot* root = 0;

// the only methods on ModalRoot are the constructor, destructor and operator shown below

ModalRoot::ModalRoot(WXHWND hwnd):
  win_()
{

  // Assume (confirmed in debugging) a default wxWindow does not have a valid hwnd.
  // Otherwise, we would need to destroy that hwnd first. --ttp
  win_.SetHWND(hwnd);
  win_.Enable(false);
}


ModalRoot::~ModalRoot()
{

  win_.Enable(true);
  win_.SetHWND(0);
}

ModalRoot::operator wxWindow*() const
{
  return &win_;
}
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

Re: access violation executing in CLR host application

Post by Alan Stewart »

It has just occurred to me that another first in how this code is being re-used is that this host application is being built as 64-bit. AFAIL all prior usage was in 32-bit host applications. I don't immediately see why this would make a difference, but perhaps.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: access violation executing in CLR host application

Post by doublemax »

Going back to this line:

Code: Select all

parent = CheckIfCanBeUsedAsParent(wxTheApp->GetTopWindow());
You say that the GetTopWindow() returns a (probably) valid value.

Does "this" have a non-NULL value at that time?

Can you step into the CheckIfCanBeUsedAsParent() call? A function call should never crash, unless the function pointer itself is wrong. Can you check the address of the function? If that was NULL, something must have gone wrong with linking the wxWidgets DLL. But then the GetTopWindow() call shouldn't have worked either...

Sorry, i really have no idea what's going on.
Use the source, Luke!
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

Re: access violation executing in CLR host application

Post by Alan Stewart »

Thanks, I'm probably not going to be able to get back on this until Monday.

Yes, I stepped into GetTopWindow() and as I recall the value of the member variable being returned was non-zero, was not a typical VS uninitialized memory value, appeared sane. My memory is that as I stepped back up the call stack from that point an exception was immediately thrown. I will look at it again as soon as I can.

It always helps to have a second set of eyes!
Alan Stewart
Knows some wx things
Knows some wx things
Posts: 44
Joined: Wed Jul 08, 2015 2:19 pm

Re: access violation executing in CLR host application

Post by Alan Stewart »

Well, the exception does not occur now, at least not at the same point. It's getting much further and I now need to resolve some issues with our code.

Since I was hung on this particular dialog I turned to implementing C++/CLI wrappers for our other dialogs. In the process I have needed to LoadLibraryEx() additional DLLs. Are there DLLs that the wxWidgets DLLs load dynamically at runtime, which the absence of would not prevent the wxWidgets DLLs from loading initially? The only DLLs I was loading before the wxWidgets DLLs were (and still are) libintl-8-vc100d.dll and libiconv-2.dll. I'm now loading many more after the wxWidgets DLLs are loaded, though most are either our product DLLs or supporting a data format such as JPEG2K. Maybe icudt36.dll and icucnv36.dll?
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: access violation executing in CLR host application

Post by doublemax »

Are there DLLs that the wxWidgets DLLs load dynamically at runtime, which the absence of would not prevent the wxWidgets DLLs from loading initially?
I never use wxWidgets as DLLs, but i'm 99% sure they are self-contained and don't require any other DLLs, maybe except the CRTs.
Use the source, Luke!
Post Reply