I’ve compiled libsass 3.3.6 into a DLL with VS 2015 using the included solution files. Running the code below causes the program to crash immediately with no output.
using System;
using System.Runtime.InteropServices;
namespace Sass.Cli {
static class Sass {
[DllImport(#"C:\...\libsass\win\bin\libsass.dll")]
public static extern String libsass_version();
}
class Program {
static void Main(string[] args) {
Console.WriteLine(Sass.libsass_version());
}
}
}
The source for the invoked function is at sass.cpp:61.
const char* ADDCALL libsass_version(void)
Both the DLL and the above code were compiled for x86. Running the VS debugger on crash gives me the following exception: Unhandled exception at 0x771A9841 (ntdll.dll) in Sass.Cli.exe: 0xC0000374: A heap has been corrupted (parameters: 0x771DC8D0).
Is this something that can be fixed or that I’ve overlooked? Or is it just the case that libsass DLLs aren’t currently working?
When a string is used as a return type then the framework assumes it was allocated by calling CoTaskMemAlloc. It then copies the content of the string and deallocation by calling CoTaskMemFree. That is the explanation for your error.
Solve it by changing the return value to IntPtr and getting the string content with Marshal.PtrToStringAnsi. You won't need to deal located anything since this version string will be static.
I can't tell what the calling convention is. You should check the code and docs to find out. Still, this function is so simple that it behaves the same way for both cdecl and stdcall so that can't explain the error. Still, you will need to get it right for the rest of the library.
Note that I am guessing a little here. You've not provided full details. You should consult the code and docs to double check my guesswork.
Related
Here's the scenario I am confronted with:
in a simple DLL, written in C, there are functions which access files, for example:
DLL_EXPORT void Virt_Hello(void) {
FILE *f = fopen("Hello_world", "w");
if (f) {
fprintf(f, "Hello world!\n");
}
fclose(f);
}
in the managed code:
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void Virt_HelloDelegate();
private IntPtr m_helloPtr;
m_helloPtr = GetProcAddress(m_libraryPtr, "Virt_Hello");
Virt_Hello = Virt_HelloDelegate)Marshal.GetDelegateForFunctionPointer(m_helloPtr, typeof(Virt_HelloDelegate));
and later, this function is called as:
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public void Hello()
{
Virt_Hello();
}
I've been reading for the last couple of days pretty much everything I could find on this topic however it still doesn't work: the file is not open, and the calling managed code/process just hangs - no exceptions are thrown either.
Tried StdCall calling convention, changed several parameters on the SecurityPermission attribute - to no avail. I've even made sure all assembly dependencies are signed.
Of course I would prefer to integrate it through C++/CLI instead of PInvoke-ing however the DLL is a blackbox for me.
Any help or suggestion how to go forward would be much appreciated.
I'm pretty sure I'm missing something obvious but right now I just can't see it.
My best regards to the community!
In my c# code I need to call a c++ function (myWrapper) that is exported by a dll that I've created.
When myWrapper returns I get the following runtime error:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
As I will show below, I already specified the calling conventions a __cdecl.
In detail, my C# code:
class myClass
{
[DllImport("MyWrapper.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void myWrapper();
public void myMethod()
{
myWrapper();
}
}
c++ code for myWrapper:
#include "IpIpoptApplication.hpp"
extern "C" __declspec(dllexport) void (__cdecl myWrapper)()
{
SmartPtr<IpoptApplication> solver = IpoptApplicationFactory();
ApplicationReturnStatus status = solver->Initialize();
}
The IpoptAppliationFactory function is imported from an external dll in IpOptApplication.hpp (which is part of an open source project and can be viewed from https://projects.coin-or.org/svn/Ipopt/stable/3.11/Ipopt/src/Interfaces/IpIpoptApplication.hpp) with this line:
extern "C" __declspec(dllexport) class Ipopt::IpoptApplication * __cdecl IpoptApplicationFactory();
The strange thing is that the error happens only when "solver->Initialize()" in myWrapper is called. If I comment the call to this method myWrapper returns without errors.
The problem is not related to the definition of "Ipopt::IpoptApplication", nor in the implementation of IpoptApplicationFactory() or Initialize() because 1) they are from a well known open source project (http://www.coin-or.org/projects/Ipopt.xml) used by thousands of programmers, 2) myWrapper works correctly if used in a standalone executable written in c++ code.
I've already googled for hours and I believe that the problem is in the way I call myWrapper but I can't find a solution.
Can anyone give me some suggestion? Thanks a lot.
Roberto
Thanks to Hans Passant the problem has been solved. I must compile "myWrapper" in release mode.
IPOPT DLLS CAN BE COMPILED ONLY IN RELEASE MODE (see readme.txt distributed with IpOpt dlls)! I've set the configuration manager to compile this project always in release mode (even when the solution is in debug).
To debug my myWrapper function (which calls IpOpt dlls), it's necessary to set in the properties of my StartUp project, the check box "Enable unmanaged code debugging"
Since unmanaged code debugging does not allow code modifications during debug, I keep diabled this if I don't need to debug myWrapper.
I hope this will help
I am working on a project that requires implementing am unmanaged windows DLL. The DLL is used to communicate with a USB device. My code is in C# and WPF.
To initialize the DLL I call a function called:
InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
When calling this function I have to pass a struct called dllInitParams and the Handle that the control is bound to.
I am using DllImport for function pointer as such:
[DllImport("myDll.dll")]
public static extern void InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
Here is my struct:
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
All of the above are in a separate class called myDllInterface.cs. Here is how I call the InitTimerDll function from my WPF form:
public IntPtr Handle
{
get { return (new System.Windows.Interop.WindowInteropHelper(this)).Handle; }
}
private void initTime_Click(object sender, RoutedEventArgs e)
{
myDllInterface.dllInitParams initParams = new myDllInterface.dllInitParams();
initParams.simp = 0;
myDllInterface.InitTimerDll(this.Handle.ToInt32(), ref initParams);
}
The first part of the above code explains how I get the handle and the initTime_Click shows how I initialize the struct, call the initTimeDll function by passing the handle and the struct to it. I have copied the dll file in the directory that the code runs in. My code compiles just fine but it creates an error when I click on the initTime button.
Error:
An unhandled exception of type 'System.AccessViolationException' occurred in ProbeCTRL.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Why is this happening?
Without knowing exactly what the InitTimerDll() function does with the 'this' pointer, I would focus on the params structure. Try adding a structure layout markup like the following:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
Also, double check that your structure is complete and accurate.
I found the problem. The code is fine the problem was the dll file, which was corrupted. A proper copy of the dll file took care of the problem. When using dll in your codes it is quite important to make sure you have accurate information, function calls, data types to passed and so on.
Thanks everyone for your help.
Have a look at the PInvoke tutorial: http://msdn.microsoft.com/en-us/library/aa288468%28v=vs.71%29.aspx
as Jim Gomes points out:
[StructLayout(LayoutKind.Sequential)]
or something similar is definitely important.
Also, you're only initializing one of the variables in your struct.
I'm writing a wrapper library using C++/CLI for an unmanaged C++ project. The goal is to expose this library to C# applications. Here's what I have so far.
#pragma once
#include "Settings.h"
#include "Settings/SettingsPrivate.h"
public ref class Settings
{
public:
Settings();
virtual ~Settings();
protected:
!Settings();
public:
unsigned char GetModel(int iNumber);
private:
CSettings* m_pSettings;
};
#include "stdafx.h"
#include "Managed/Settings.h"
Settings::Settings()
{
// Pointer to unmanaged object
m_pSettings = new CSettings();
}
Settings::~Settings()
{
this->!Settings();
}
Settings::!Settings()
{
if (m_pSettings)
{
delete m_pSettings;
m_pSettings = NULL;
}
}
unsigned char Settings::GetModel(int iNumber)
{
return m_pSettingss->GetModel(iNumber);
}
The code executes fine in the test application I wrote. The function call succeeds. The problem is that when the GC Finalizes this object, it throws an exception.
An unhandled exception of type 'System.AccessViolationException' occurred in Wrapper.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I can't see any obvious reason why this exception is being thrown. I tried disposing of the object explicitly by calling Dispose from my C# application. It still throws the same exception.
Here's the test application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WrapperTest
{
class Program
{
static void Main(string[] args)
{
Settings settings = new Settings();
byte b = settings.GetModel(0);
settings.Dispose();
return;
}
}
}
Would someone point out what I'm doing wrong??
It was a project configuration error. The code actually ran fine in Release mode.
In debug mode I linked in some release DLL's when I should have been statically linking against debug libraries. Why this caused memory corruption I haven't yet investigated but it has solved the problem.
Otherwise the code posted above is correct.
You should enable more verbose heap debugging functionality. I tested your code and it did not fail for me. I had to use malloc/free instead of new/delete as you didnt define CSettings, however the effect should be the same.
I added this to make sure I had enough heap churn to trigger a failure if their was any corruption;
unsigned char Settings::GetModel(int iNumber)
{
for(int i=0; i < iNumber; i++)
free(malloc(1024));
return iNumber;
}
For me your code worked with no failure. You should look into some of your compilation settings, are you linking to an external library for CSettings? If so you need to make sure the CRT is the same version, etc. Also you know you have to use one of the DLL run time's not /MT or /MTd.
I am interested in the shortest, neatest piece of C# code around that will reliably produce a segfault - ideally without directly calling any unmanaged code.
What you're after is somewhat unclear but I suppose this is as good as any answer so far, and it is about as minimal as you can get.
System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.Zero);
Michael's answer wasn't working for me, perhaps that case is caught now. Marshal.ReadInt32() just gives me a "SystemError: Attempted to read or write protected memory." with .NET 4.5 on Windows for various passed values. I used the following however which segfaults for me both on Windows and under mono 4.0.4.1:
using System.Runtime.InteropServices;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void UNMANAGED_CALLBACK();
public void Crash()
{
var crash = (UNMANAGED_CALLBACK)Marshal.GetDelegateForFunctionPointer((IntPtr) 123, typeof(UNMANAGED_CALLBACK));
crash();
}
As noted in the comments above, there's no such thing as a segfault in Windows, and you didn't say anything about mono on Linux. So I'm going to assume you actually meant an access violation.
Here's a way to get one:
unsafe {
int* a = (int*) -4;
*a = 0;
}
(Must be compiled with the /unsafe option.)
My first try used 0 as the address, but that turned out to throw a plain old NullReferenceException, which you can get without unsafe code. But the negative address gets an AccessViolationException on my Vista x64 box.
Compile with csc with the /unsafe option:
class Program
{
static void Main(string[] args)
{
unsafe
{
int *p = null;
*p = 5;
}
}
}