Access Violation Exception

I have a C # program that calls C dll, which in turn calls java dll (built using a third-party jet excelsior program). I pass the xml string from C # to java, and java then returns the string to C # for processing.

This works on the first iteration, but then on the second iteration I get the following exception ...

Attempted to read or write protected memory. It is often that other memory is corrupted.

Here is what I would call the appropriate code, but if you need anything else, let me know.

C # Call for C dll

public static class DllCall { [DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)] public static extern int initDll([MarshalAs(UnmanagedType.LPStr)] string userDllName); [DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)] public static extern void finalizeDll(); [DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)] public static extern UInt32 newClassInstance(String rootPath, String cfgPath, String logPath ); [DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)] public static extern String request(UInt32 hClassInst, [MarshalAs(UnmanagedType.LPStr)] String input); [DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)] public static extern void close(); } 

Method in C dll that throws an error

 const char* request(jobject obj, char* input ) { jstring inputString; jstring outputString; const char *nativeString; jmethodID mID = (*env)->GetMethodID (env, jClass, "request", "(Ljava/lang/String;)Ljava/lang/String;"); if (!mID){ printf("\nError: dllClass.request() not found\n"); return 0; } inputString = (*env)->NewStringUTF(env, input); outputString = (*env)->CallObjectMethod(env, obj, mID, inputString); nativeString = (*env)->GetStringUTFChars(env, outputString, 0); return nativeString; } 

As requested, here is a C # code that actually throws an exception.

  public string request(string xmlInput) { LogManager.logMessage("Sending request to Java. Request is - " + xmlInput); string rs =""; Console.Write("Making request"); //this works fine rs = DllCall.request(hClass, xmlInput); Console.Write("---> request() rs = {0}\n", rs); // this throws the error rs = DllCall.request(hClass, "<?xml version='1.0' encoding='utf-8'?><moo><request name=\"Panel.Open.GetSelectionTemplate\"/></moo>"); return rs; } 

In response to Daniel, env is declared here

 #include <jni.h> #include <windows.h> JNIEnv *env; JavaVM *jvm; HANDLE hUserDll; jclass jClass; char* dllname; 

And this is how it is initialized.

 int initDll(char* userDllName) { jClass = NULL; hUserDll = loadDll(userDllName); dllname = userDllName; initJavaRT(hUserDll, &jvm, &env); jClass = lookForClass(env, "XActMain/XActGeminiX3/XActGeminiX3IFX"); return jClass ? 1 : 0; } /* * Initialize JET run-time. */ void initJavaRT(HANDLE myDllHandle, JavaVM** pjvm, JNIEnv** penv) { int result; JavaVMInitArgs args; JNI_GetDefaultJavaVMInitArgs_func = (jint (JNICALL *) (void *args)) GetProcAddress (myDllHandle, "JNI_GetDefaultJavaVMInitArgs"); JNI_CreateJavaVM_func = (jint (JNICALL *) (JavaVM **pvm, void **penv, void *args)) GetProcAddress (myDllHandle, "JNI_CreateJavaVM"); if(!JNI_GetDefaultJavaVMInitArgs_func) { printf ("%s doesn't contain public JNI_GetDefaultJavaVMInitArgs\n", dllname); exit (1); } if(!JNI_CreateJavaVM_func) { printf ("%s doesn't contain public JNI_CreateJavaVM\n", dllname); exit (1); } memset (&args, 0, sizeof(args)); args.version = JNI_VERSION_1_2; result = JNI_GetDefaultJavaVMInitArgs_func(&args); if (result != JNI_OK) { printf ("JNI_GetDefaultJavaVMInitArgs() failed with result %d\n", result); exit(1); } /* * NOTE: no JVM is actually created * this call to JNI_CreateJavaVM is intended for JET RT initialization */ result = JNI_CreateJavaVM_func (pjvm, (void **)penv, &args); if (result != JNI_OK) { printf ("JNI_CreateJavaVM() failed with result %d\n", result); exit(1); } printf ("JET RT initialized\n"); fflush (stdout); } 

This is in response to Jos's initialization comment ...

 public class Test { public UInt32 hClass; public Test() { initDll(); newClassInstance(rootConfig, config, logFile); } ........ public void newClassInstance(string rootPath, string cfgPath, string logPath) { hClass = DllCall.newClassInstance(rootPath, cfgPath, logPath); Console.Write("---> hClass = {0}\n", hClass); } public void initDll() { int rc = DllCall.initDll("dllClass.dll"); Console.Write("---> initDll() rc = {0}\n", rc); } 

Hans pointed to the following link potential response

However, I am not sure how to change the current code to host this solution.

As I said, it works once, and then falls on the second iteration.

+4
source share
1 answer

I'm not sure why it works the first time, but you are passing a class object ( hClass ) to request instead of an instance of this class.

 rs = DllCall.request(hClass, xmlInput); //The error is thrown on this line 

See if this fixes the problem:

 public string request(string xmlInput) { LogManager.logMessage("Sending request to Java. Request is - " + xmlInput); string rs =""; Console.Write("Making request"); UInt32 hClassInst = DllCall.newClassInstance(rootPath, cfgPath, logPath); // <-- New line, using your own rootPath, cfgPath, logPath variables rs = DllCall.request(hClassInst, xmlInput); // <-- Modified line, using hClassInst instead of hClass Console.Write("---> request() rs = {0}\n", rs); return rs; } 

If this fixes the problem, you should probably reorganize it and put the call to newClassInstance on an earlier initialization method.

+1
source

Source: https://habr.com/ru/post/1389458/


All Articles