Leon Bohmann
Leon Bohmann

Reputation: 402

AccesViolationException in C++/CLI Wrapper for native C

I am writing an application in C# which uses a C++/CLI Wrapper .dll which again uses another C++/CLI Wrapper for native C code.

Further Explanation:

My C# Application (to which I refer as Reporter) is nothing more than a windows form which calls the first C++/CLI Wrapper (to which I refer to as Control) which contains a UserControl. This UserControl is a GUI in order to call the last .dll (refered to as Generator). I do this because I want to use my Control in other projects and I do not want to hassle with the marshalling of my types like char *.

So here's my problem: For some times I can call my Generator-Function just as planned. But after some calls, I get an AccessViolationException.

My Generator contains loads of C-functions and also global C variables. Everything is marked properly as extern "C". As I determined, the Violation occurs when I try to a global variable.

I was trying to put all the global variables in my wrapper-class in Generator but I failed, because I could not convert all the C-types into a managed-type.

After I call the functions I was free(x)ing the space of my variables. Before commented that out, I wasn't able to call the function more than twice. Now (after commenting out) I am able to call the function in Generator 4 times. Always.

How can I work around this? Is there a way to give my function like "administrative rights" in order to allow them to do what they want with the global variables?

Thanks to all in advance, I am stuck with this for almost a month now and did much research on how to write wrapper-classes.

Leon

EDIT:

This is how I declare the concerning global variable:

"globals.h"

extern "C"{

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>  // fuer va_start, va_end
#include <string.h>
#include <malloc.h>
#include <windows.h>
//#include <omp.h>


// Used to prevent redefinition, _HAUPT_ is only defined in .dll-Header
#ifdef _HAUPT_
/*#define _HAUPT_*/
#define  TYPE

    int extreme = 0;

#else 
#define TYPE extern

    TYPE int extreme;

#endif

}

However, while writing my edit here I found out the problem was on my side. I mixed up a self-written LinkedList, error occured when I was trying to declare an unallocated pointer with a value.

Upvotes: 3

Views: 379

Answers (2)

Pooven
Pooven

Reputation: 1764

I agree with Taus:

AccessViolationExceptions are most often caused by accessing freed/unallocated memory or similar. Admin rights have nothing to do with it. A minimal example would go along way towards identifying the problem

The marshaler will generally try to create a managed (C#) representation of that data and then attempt to deallocate/free the unmanaged data (C++). However, you're probably not allocating memory in C/C++ in the way that the marshaler is expecting, or maybe you're were not expecting the marshaler to try and free the memory for you.

If the default deallocation behaviour doesn't match your use case then you can handle the deallocation (if at all) of the C++ object manually by using an IntPtr in your C# code. For example, if you're returning a string literal from unmanaged code, then the memory should not be deallocated. See this post for an example.

If you post the code snippet showing how you're allocating memory in your unmanaged application, how you're exposing the data, and finally, how you're accessing it in your C# application, we can help you pinpoint the problem.

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 942538

You cannot get a useful answer for a question like this. Access violations are the standard way in which C code fails and there are numerous ways to invoke undefined behavior in that language. The kind that corrupts memory, such corruption eventually crashes your code. The exact place where the code fails is very rarely close to the statement with the bug. And it can take a while before the corruption has an affect. Spending a week or more to find the bug is not unusual at all.

Basic ways to go about it:

  • Write unit tests that exercise the C code, helps to narrow down the number of code execution paths that cause the corruption.
  • Be sure to build the C code with all debug features turned on, enabled by default for the Debug build in the MSVC compiler. You need all the help you can get from /MDd and /RTC.
  • Use Application Verifier, a tool that can detect heap corruption and show you what statement caused it. Best used on a unit test that fails.
  • Contemplate if the C language actually is useful to you to get the job done. You can squeeze an extra ~25% perf out of native code over managed code, give or take, but the price is rather a high one if you can't make it work reliably or lose a month of your life. Hardware is a lot cheaper than your hours.

Upvotes: 1

Related Questions