1

Problem: Getting an error when running my .exe

An unhandled exception of type 'System.AccessViolationException' occurred in AddingWrapper.dll

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

In the console it writes this:

Unhandled Exception: System.AccessViolationException : attempted to read or write protected memory. This is often an indication that other memory is corrupt. at gcroot (Add ^).. P$AAVAdd@@(gcroot(Add^)) at AddingWrapper.Adding(AddingWrapper, Int32* x, Int32* y)

Code snippet:

VB code:

Public Class Add
  Public Function Adding(ByVal x As Double, ByVal y As Double) As Integer
      Return x + y
   End Function

End Class

AddingWrapper.h:

#pragma once
#include "stdafx.h"

class AddingWrapperPrivate;


class __declspec(dllexport) AddingWrapper {

private: AddingWrapperPrivate* _private;
public: AddingWrapper();
        int Adding(int* x, int* y);
       ~AddingWrapper();

};

AddingWrapper.cpp

#include "stdafx.h"

#include "AddingWrapper.h"

#using "Class1.dll"
#include <msclr\auto_gcroot.h>
using namespace System::Runtime::InteropServices;

class AddingWrapperPrivate {
  public: msclr::auto_gcroot<Add^> add;
};

AddingWrapper::AddingWrapper()
{
    _private = new AddingWrapperPrivate();
    _private->add = gcnew Add();
};
int AddingWrapper::  Adding(int* x, int* y) {
    return _private->add->Adding(*x, *y);
};
AddingWrapper::~AddingWrapper()
{
    delete _private;
};

calling code:

 #include "stdafx.h"
 #include "AddingWrapper.h"
 #include <iostream>
    int main()
{
  int *a = 0;
   int *b = 0;
   AddingWrapper *add;
   int results =  add->Adding(a,b);
   std::cout << "here is the result";
   std::cout << results;
   return 0;
 }

Could it be due to my Class1.dll in AddingWrapper.cpp is using VB.net? Or it's a question of other issues? All the other threads seem to all differ in answer (i.e one is suggesting the user account doesn't have all the rights to the computer). If ever I missed on of those thread, please link it to me, this error is killing me

I should also add this error is at run time not compile time.

MMTYL
  • 15
  • 1
  • 6
  • AddingWrapper is being exported from the dll. What calls that code and what does that look like? – Niall Jun 08 '16 at 20:48
  • A VB.NET program does not know how to properly construct and destroy a native C++ object. You get the AVE because the *this* object reference is garbage, the constructor was never called. You can only safely export a static member function or a plain C function. Or a `public ref class`, a managed class like any VB.NET class, largely the point of using C++/CLI. – Hans Passant Jun 08 '16 at 20:48
  • Mhm @HansPassant , why would the VB.net program know how to destroy the C++ pointer as the .exe execution is in native C++. The VB code only takes in 2 ints ( or double whatever I put in there) and returns a reference to the int memory space no? I thought that's all that was needed. I just think something goes wrong in between my classes and I can't seem to be able to debug it as it happens at run time and I've never had to debug at run time. Plus, if I run the program in debug mode in VS 2015, it only gives me a C2059 / C2018 in my .lib file. So it's very disorienting to find the problem – MMTYL Jun 09 '16 at 12:37
  • @Niall yes It is being exported to native C++. I apologize, I should've been more precised, thought I was being. – MMTYL Jun 09 '16 at 12:38

2 Answers2

2

In the main function, you are using a "null" object pointer and passing in NULL pointers - that will cause the error you are seeing.

int main()
{
   int a = 1;
   // ^^^ remove the pointer (and give it a "interesting" value)
   int b = 2;
   // ^^^ remove the pointer
   AddingWrapper add; // remove the pointer (or allocate with new)
   //          ^^^ remove the pointer
   int results = add.Adding(&a, &b); // pass in the address of the integers
   //              ^^^ syntax change

   std::cout << "here is the result";
   std::cout << results;
   return 0;
 }

The variable a, b and add where only pointers, pointing to nothing; this causes access violations. Changing them to be automatic objects ("on the stack") will fix this. If dynamic objects are needed, you can new them (and delete them afterwards); but favour library utilities such as std::shared_ptr and std::unique_ptr etc. to help manage the lifetime of the object.

Niall
  • 30,036
  • 10
  • 99
  • 142
  • mhm, interesting. I'm not used to using pointers as I come from purely managed languages. However, I would assume that int* a = 5 would point to a memory address that contains the integer 5. As for your answer, it worked. I didn't think my DLL would work but god, I spent 10 hours on this and all that was wrong was my pointers, care to enlighten me on why the pointers were lost in oblivion? – MMTYL Jun 09 '16 at 13:28
  • The pointers were note lost, the objects were not created. To create an object and access it via a pointer, the syntax is `int* a = new int(5);` this creates and integer, with the value 5 and assigns it to the pointer `a`. To clean it up, use `delete a;`. Using a more modern C++ would be `auto a = std::make_unique(5);` and the type for `a` is deduced (`unique_ptr`) and all the memory is cleaned up by the `unique_ptr`. – Niall Jun 09 '16 at 13:53
  • In general, unless a dynamic lifetime is required (via `shared_ptr` or `unique_ptr`), use automatic values ("on the stack"). – Niall Jun 09 '16 at 13:54
  • mhm thanks for pointing that out. I had to teach myself pointers on the go and some tutorials just initialize it as int* x = 5 for instance. The more you know. Thank you! – MMTYL Jun 09 '16 at 13:55
  • There is a book list here; http://stackoverflow.com/q/388242/3747990, with some very good books on all levels (and some online as well). – Niall Jun 09 '16 at 13:56
1

Several things:

  • You haven't shown your VB code. Since you've written an unmanaged class, not a managed one, it seems likely that either the import is not correct, or that you're passing a bad pointer.
  • Why are you passing an int* to the wrapper, only to dereference it right there? Why not pass an int?
  • You're in C++/CLI, why are you not writing a managed class? You wouldn't need auto_gcroot, and you don't need to deal with DLL imports/exports: VB.Net would be able to see your class the same as it can see any .Net class, and reference it just as easily as you can reference any .Net library.

Edit

OK, it wasn't obvious that you were trying to call some VB.Net code from C++. I thought you were trying to go the other direction.

The problem is almost certainly that you're passing a bad pointer to AddingWrapper::Adding.

You don't need to pass a pointer for basic data types, so you can get rid of that entire thing if you want. The fact that it's a double in VB but an int in C++ is fine, C++/CLI knows that the VB code takes a double and will convert appropriately.

Also, note that you're not passing a pointer between managed and unmanaged code. You're passing a pointer from one unmanaged class to another unmanaged class (whatever calls AddWrapper, to AddWrapper), but across the managed/unmanaged border, you're passing a plain old int.

David Yaw
  • 27,383
  • 4
  • 60
  • 93
  • Mhm the VB code is rather straight forward so I didn't think of putting it in. It's in now ( right after I answer). As for the int* I thought I had to pass a pointer reference because it was going between unmanaged / managed code. ( Keep in mind, it's my first time playing with unmanaged code). For your 3rd point, I thought using __gcroot was needed when dealing with managed code in native c++ ( I do mean using my VB.net function in native C++) – MMTYL Jun 08 '16 at 20:42
  • OK, it wasn't obvious, and I thought you were trying to call C++ from VB. See edit. – David Yaw Jun 08 '16 at 20:51
  • Ah thank you. I'm guessing it is very unorthodox. Fact of the matter is that a company needs to upgrade their code and as the intern I'm the one doing the crap job ( not complaining, just saying). Half their team works in VB.net and only knows that, and the other half in native C++. I'll add something else on top of that ( I did remove the wrapper, but something still goes on at run time.). However, I'll ask this: what do you mean by bad pointer? I.e: my program loses my actual pointer in memory and just grabs another one? – MMTYL Jun 09 '16 at 12:33
  • From the error it seems the error happens at gcroot(Add^), which seems to screw everything afterwards, because if there's no pointer there, it can't access the VB file. However, this error ( as said above ) only happens at run time which I've never had to debug before . – MMTYL Jun 09 '16 at 12:51