AccessViolationException calling native C++ code from managed C++ (wrapper for ASP.NET) - c++

I have a ASP.NET web application that needs access to a function in a native C++ DLL. To do this, I wrapped the native C++ code using a managed C++ DLL. Calling the native function from the managed code, however, results in a System.AccessViolationException. I do not have to the native code, but it will write to the file system (logs), which was my first guess, but according to other SO answers the AccessViolationException is caused by memory issues.
The code is pretty simple, this is the unshortened version:
#include <msclr\marshal_cppstd.h>
#define AS_NATIVE_STRING(managed_string) msclr::interop::marshal_as<std::string>(managed_string)
#define AS_MANAGED_STRING(native_string) msclr::interop::marshal_as<String^>(native_string)
ReturnStruct ManagedClass::execute_managed(String ^param1, String ^param2)
{
auto param1_native = AS_NATIVE_STRING(param1);
auto param2_native = AS_NATIVE_STRING(param2);
// here I get the exception:
auto result = _wrapped_api->execute_native(param1_native, param2_native);
if (is_error_string(result.first))
throw gcnew System::Exception(AS_MANAGED_STRING(result.second));
auto result1 = AS_MANAGED_STRING(result.first);
auto result2 = AS_MANAGED_STRING(result.second);
return ReturnStruct(result1, result2);
}
Any hints on what could be causing it? I did indeed look at similar questions, but no answer seemed to really fit my problem.
Edit:
Using HandleProcessCorruptedStateExceptionsAttribute I was able to determine the error message of the AccessViolationException: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

After further investigation, I have come to the conclusion, that I basically cannot fix this on my end. I created a mock version of the DLL myself to be able to step in and see if the type conversion is correct and the parameters contain the correct strings. This was the case. This does not really help me, but maybe someone else might find a problem in his/her code with this approach.
I will just contact the authors of the wrapped api.

Related

QuickJS: Possible memory leak due to modifying function prototype

I've encountered what seems like a bug in the QuickJS JavaScript engine. I've submitted a GitHub issue, but am also asking here to see if it might be user error, and/or to find out if others have encountered similar issues.
The following test code:
#include <string>
#include "quickjs.h"
int main() {
auto runtime = JS_NewRuntime();
auto context = JS_NewContext(runtime);
std::string source =
"function foo() {}\n"
"foo.prototype.bar = function() {};";
JS_Eval(context, source.c_str(), source.size(), "", JS_EVAL_TYPE_GLOBAL);
JS_FreeContext(context);
JS_FreeRuntime(runtime);
}
Produces the assertion:
Assertion failed: (list_empty(&rt->gc_obj_list)), function JS_FreeRuntime
Using the 'dump leaks' feature outputs the following:
Object leaks:
ADDRESS REFS SHRF PROTO CLASS PROPS
0x1071d4bc0 1 0* 0x1071c5510 Function { length: 0, name: 14'', prototype: [autoinit 0x1071c4e80 0 0x0] }
Which seems to suggest that modifying the function prototype is causing a memory leak. (This doesn't happen if the function prototype is left unmodified.)
Is there anything obviously wrong with my test code? Perhaps misuse of the API? If not, has anyone else run into this issue or similar issues with QuickJS?
For anyone who might stumble on this in the future, this was due to incorrect API usage. The leak wasn't due to the JavaScript code itself, but rather because JS_Eval() returns a JSValue, which needs to be freed using JS_FreeValue().

Embedding Script in C++

I have a quit big c++ program and I want to have a function which I can edit in a text file to change the behavior of my c++ program without compiling it again.
To achieve this I thought I could embed a script in my c++ program.
My function should take two c++ objects and return a boolean in relation to the two objects and their members.
The pseudo code would be similar to the following:
//In c++ program
CppObject cpp1, cpp2;
ScSriptObject o1 = transform(cpp1);
ScriptObject o2 = transform(cpp2);
boolean result = call function(o1, o2);
//Script function in text file
boolean function(Object o1, Object o2)
{
return do_something(o1, o2)
}
I would like to know if there is another maybe better solution. And with which scripting languages can this be done easily and how can it be done?
I have already taken a look at python and Python/C API, but I had some troubles to get the basic examples working and I'm wondering if there is a simpler option.
Thank you for your help :)
If you're using linux, you could use system function to call for an external script which you could edit whenever you decide to, without compiling again. Eg.:
int res = system("/usr/local/bin/myscript.sh");
if (res == 0)
{
// exited normally
}
else
{
// abnormal exit
}
On windows you could use a similar approach, as system in platform independent. One more thing, mind the endianness of the result!
For further reading about system, you could use this answer or this almost full explanatory link on cplusplus.com.
Hope it helps, cheers.

Exception Handling in /clr MFC Application (compiled with /EHa)

We have a large MFC application that is in the process of being updated. It has been modified to add in some .NET components (some of the DLLs now have managed & native classes), the idea is that the old code will be phased out eventually.
The app has many DLLs with native C++ classes exported, and used by the application.
On trying to test the app we now find ANY exception seems to cause the app to crash, even though these exceptions are in theory being caught in the same function.
example:
CString AddressClass::GetPostalAddress()
{
CString address;
try {
address = (LPCSTR)(_bstr_t)m_pCommand->GetParameters()->Item["PostalAddress"]->Value;
}
catch ( _com_error& )//exception occurs if postal address is NULL
{
address = _T("");
}
return address;
}
The _com_error is not being caught when compiling with /clr and /EHa (Vs2015 update 3). Without /clr it works fine and has been operational for years. From the documentation I have read my understanding is this should work, but clearly I am mistaken.
The code responsible for generating the error is in comutil.h:
inline void CheckError(HRESULT hr)
{
if (FAILED(hr)) {
_com_issue_error(hr);
}
}
The information from the debugger is:
An exception of type 'System.Runtime.InteropServices.SEHException' occurred in XXX.dll and wasn't handled before a managed/native boundary
Additional information: External component has thrown an exception.
Is there anyway to get this working without rewriting huge amounts of code?
Thanks.
Answer from short comment, since it seems to have helped:
Generally speaking: You should not compile these with /clr. Separate your old code vs your new CLR-using code, just compile new code with /clr, compile old code/files directly native. You can still link everything together in a clr-enabled DLL.
What we do is to compile all the native stuff in separate static LIB projects, and then link these into /clr enabled projects - having separate compiler switches for individual source files inside one project is always a tad confusing. But then, it may still be the way to go for you. Depends on the mixture and calling patterns, I guess.
I'll add that I view /clr mostly as a rather powerful glue system, than something you should target for the full app stack.

AccessViolationException reading memory allocated in C++ application from C++/CLI DLL

I have a C++ client to a C++/CLI DLL, which initializes a series of C# dlls.
This used to work. The code that is failing has not changed. The code that has changed is not called before the exception is thrown. My compile environment has changed, but recompiling on a machine with an environment similar to my old one still failed. (EDIT: as we see in the answer this is not entirely true, I was only recompiling the library in the old environment, not the library and client together. The client projects had been upgraded and couldn't easily go back.)
Someone besides me recompiled the library, and we started getting memory management issues. The pointer passed in as a String must not be in the bottom 64K of the process's address space. I recompiled it, and all worked well with no code changes. (Alarm #1) Recently it was recompiled, and memory management issues with strings re-appeared, and this time they're not going away. The new error is Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I'm pretty sure the problem is not located where I see the exception, the code didn't change between the successful and failing builds, but we should review that to be complete. Ignore the names of things, I don't have much control over the design of what it's doing with these strings. And sorry for the confusion, but note that _bridge and bridge are different things. Lots of lines of code missing because this question is already too long.
Defined in library:
struct Config
{
std::string aye;
std::string bee;
std::string sea;
};
extern "C" __declspec(dllexport) BridgeBase_I* __stdcall Bridge_GetConfiguredDefaultsImplementationPointer(
const std::vector<Config> & newConfigs, /**< new configurations to apply **/
std::string configFolderPath, /**< folder to write config files in **/
std::string defaultConfigFolderPath, /**< folder to find default config files in **/
std::string & status /**< output status of config parse **/
);
In client function:
GatewayWrapper::Config bridge;
std::string configPath("./config");
std::string defaultPath("./config/default");
GatewayWrapper::Config gwtransport;
bridge.aye = "bridged.dll";
bridge.bee = "1.0";
bridge.sea = "";
configs.push_back(bridge);
_bridge = GatewayWrapper::Bridge_GetConfiguredDefaultsImplementationPointer(configs, configPath, defaultPath, status);
Note that call to library that is crashing is in the same scope as the vector declaration, struct declaration, string assignment and vector push-back
There are no threading calls in this section of code, but there are other threads running doing other things. There is no pointer math here, there are no heap allocations in the area except perhaps inside the standard library.
I can run the code up to the Bridge_GetConfiguredDefaultsImplementationPointer call in the debugger, and the contents of the configs vector look correct in the debugger.
Back in the library, in the first sub function, where the debugger don't shine, I've broken down the failing statement into several console prints.
System::String^ temp
List<CConfig^>^ configs = gcnew List<CConfig ^>((INT32)newConfigs.size());
for( int i = 0; i< newConfigs.size(); i++)
{
std::cout << newConfigs[i].aye<< std::flush; // prints
std::cout << newConfigs[i].aye.c_str() << std::flush; // prints
temp = gcnew System::String(newConfigs[i].aye.c_str());
System::Console::WriteLine(temp); // prints
std::cout << "Testing string creation" << std::endl; // prints
std::cout << newConfigs[i].bee << std::flush; // crashes here
}
I get the same exception on access of bee if I move the newConfigs[i].bee out above the assignment of temp or comment out the list declaration/assignment.
Just for reference that the std::string in a struct in a vector should have arrived at it's destination ok
Is std::vector copying the objects with a push_back?
std::string in struct - Copy/assignment issues?
http://www.cplusplus.com/reference/vector/vector/operator=/
Assign one struct to another in C
Why this exception is not caught by my try/catch
https://stackoverflow.com/a/918891/2091951
Generic AccessViolationException related questions
How to handle AccessViolationException
Programs randomly getting System.AccessViolationException
https://connect.microsoft.com/VisualStudio/feedback/details/819552/visual-studio-debugger-throws-accessviolationexception
finding the cause of System.AccessViolationException
https://msdn.microsoft.com/en-us/library/ms164911.aspx
Catching access violation exceptions?
AccessViolationException when using C++ DLL from C#
Suggestions in above questions
Change to .net 3.5, change target platform - these solutions could have serious issues with a large mult-project solution.
HandleProcessCorruptedStateExceptions - does not work in C++, this decoration is for C#, catching this error could be a very bad idea anyway
Change legacyCorruptedStateExceptionsPolicy - this is about catching the error, not preventing it
Install .NET 4.5.2 - can't, already have 4.6.1. Installing 4.6.2 did not help. Recompiling on a different machine that didn't have 4.5 or 4.6 installed did not help. (Despite this used to compile and run on my machine before installing Visual Studio 2013, which strongly suggests the .NET library is an issue?)
VSDebug_DisableManagedReturnValue - I only see this mentioned in relation to a specific crash in the debugger, and the help from Microsoft says that other AccessViolationException issues are likely unrelated. (http://connect.microsoft.com/VisualStudio/feedbackdetail/view/819552/visual-studio-debugger-throws-accessviolationexception)
Change Comodo Firewall settings - I don't use this software
Change all the code to managed memory - Not an option. The overall design of calling C# from C++ through C++/CLI is resistant to change. I was specifically asked to design it this way to leverage existing C# code from existing C++ code.
Make sure memory is allocated - memory should be allocated on the stack in the C++ client. I've attempted to make the vector be not a reference parameter, to force a vector copy into explicitly library controlled memory space, did not help.
"Access violations in unmanaged code that bubble up to managed code are always wrapped in an AccessViolationException." - Fact, not a solution.
but it was the mismatch, not the specific version that was the problem
Yes, that's black letter law in VS. You unfortunately just missed the counter-measures that were built into VS2012 to turn this mistake into a diagnosable linker error. Previously (and in VS2010), the CRT would allocate its own heap with HeapAlloc(). Now (in VS2013), it uses the default process heap, the one returned by the GetProcessHeap().
Which is in itself enough to trigger an AVE when you run your app on Vista or higher, allocating memory from one heap and releasing it from another triggers an AVE at runtime, a debugger break when you debug with the Debug Heap enabled.
This is not where it ends, another significant issue is that the std::string object layout is not the same between the versions. Something you can discover with a little test program:
#include <string>
#include <iostream>
int main()
{
std::cout << sizeof(std::string) << std::endl;
return 0;
}
VS2010 Debug : 32
VS2010 Release : 28
VS2013 Debug : 28
VS2013 Release : 24
I have a vague memory of Stephen Lavavej mentioning the std::string object size reduction, very much presented as a feature, but I can't find it back. The extra 4 bytes in the Debug build is caused by the iterator debugging feature, it can be disabled with _HAS_ITERATOR_DEBUGGING=0 in the Preprocessor Definitions. Not a feature you'd quickly want to throw away but it makes mixing Debug and Release builds of the EXE and its DLLs quite lethal.
Needless to say, the different object sizes seriously bytes when the Config object is created in a DLL built with one version of the standard C++ library and used in another. Many mishaps, the most basic one is that the code will simply read the Config::bee member from the wrong offset. An AVE is (almost) guaranteed. Lots more misery when code allocates the small flavor of the Config object but writes the large flavor of std::string, that randomly corrupts the heap or the stack frame.
Don't mix.
I believe 2013 introduced a lot of changes in the internal data formats of STL containers, as part of a push to reduce memory usage and improve perf. I know vector became smaller, and string is basically a glorified vector<char>.
Microsoft acknowledges the incompatibility:
"To enable new optimizations and debugging checks, the Visual Studio
implementation of the C++ Standard Library intentionally breaks binary
compatibility from one version to the next. Therefore, when the C++
Standard Library is used, object files and static libraries that are
compiled by using different versions can't be mixed in one binary (EXE
or DLL), and C++ Standard Library objects can't be passed between
binaries that are compiled by using different versions."
If you're going to pass std::* objects between executables and/or DLLs, you absolutely must ensure that they are using the same version of the compiler. It would be well-advised to have your client and its DLLs negotiate in some way at startup, comparing any available versions (e.g. compiler version + flags, boost version, directx version, etc.) so that you catch errors like this quickly. Think of it as a cross-module assert.
If you want to confirm that this is the issue, you could pick a few of the data structures you're passing back and forth and check their sizes in the client vs. the DLLs. I suspect your Config class above would register differently in one of the fail cases.
I'd also like to mention that it is probably a bad idea in the first place to use smart containers in DLL calls. Unless you can guarantee that the app and DLL won't try to free or reallocate the internal buffers of the other's containers, you could easily run into heap corruption issues, since the app and DLL each have their own internal C++ heap. I think that behavior is considered undefined at best. Even passing const& arguments could still result in reallocation in rare cases, since const doesn't prevent a compiler from diddling with mutable internals.
You seem to have memory corruption. Microsoft Application Verifier is invaluable in finding corruption. Use it to find your bug:
Install it to your dev machine.
Add your exe to it.
Only select Basics\Heaps.
Press Save. It doesn't matter if you keep application verifier open.
Run your program a few times.
If it crashes, debug it and this time, the crash will point to your problem, not just some random location in your program.
PS: It's a great idea to have Application Verifier enabled at all times for your development project.

Getting strange error when attempting to convert Unmanaged C++ class to Managed C++ class (for use in .net)

Greetings,
First off, I am not a C++ developer, so please forgive my shortcomings....
I am attempting to take another developer's C++ unmanaged code and re-work it so it can be called from a managed DLL from our c#.net application. Please keep in mind that I'm a .net developer, and I haven't touched C++ in like 12 years. And when I did... I made a rock-paper-scissor game. :(
Anyway... I found a nice little note from another developer on a forum that suggested we go ahead and add a garbage collector to the class in the .h file with "Public __gc". Well, there are two classes I'm trying to convert to managed code, so I went ahead and did that... and one of them just instantly worked! The other... well, is throwing this error:
'cannot convert parameter 5 from 'char *__gc *' to 'char **'
Ok, so I know this has something to do with pointers pointing to more pointers and stuff... but here are the variables in question that DID work when the garbage collector wasn't added to the class name, and now won't build with it added:
<<< HEADER FILE >>>
public __gc class bob
{
...
public:
char *img_buff;
...
int init(void);
}
<<< CPP FILE >>>
int init(void)
{
...
nRet = is_AllocImageMem(hcam,
img_wid,
img_hgt,
depth,
&img_buff, << doesn't like it here
&mem_id );
...
}
Any suggestions or ideas? I just don't know enough about "*" and & and pointers and stuff in C++.
Thanks in advance. Best wishes!!!
What version of Visual Studio do you have? The __gc stuff is Managed C++, which was awful. You want C++/CLI, where the magic words are public ref class. Still, no matter which way you do this, you're going to have to understand pointers a little bit, because you're going to have code that says "I take a native pointer" and you intend to hand it a managed reference to something on the garbage collected heap. You'll have to change that code to make it work.
I am pretty sure using PInvoke is going to be a better plan for you because it won't require as much tweaking of the C++ code. If you have C++ expertise on the team my answer would be different.