473,325 Members | 2,860 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

Unmanaged dll interop problem.

Hi,

I have a logger.dll (unmanaged c++ dll compiled in vs2005).

I have a C# interop to use that dll in managed code implemented in
Interfaces.dll (used by other C# dlls).

I also have a number of other C# dlls referencing Interfaces.dll and
using logger.dll interop for logging.

The problem is that calls to logger.dll functions may occasionally
fail with error "Attempted to read or write protected memory".

I understand that it may be the reason of bad pointers. What I don't
understand is how it may happen.

After some testing it looks like it happens when interop is used from
multiple threads. It happens on some client servers and on 1 of 3
computers used for testing (2k3 server + sp1 + .net 2.0).

Interop is like this (brief):

namespace LoggerInterop {

#region Includes

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

using LogId = System.UInt32;
using LogResult = System.UInt32;

#endregion

public class Log
{
#region Message

public enum MessageType { ... }

public class Message : IDisposable
{
#region Interop

internal enum AttachmentType { ... }

[ StructLayout(LayoutKind.Sequential, Pack = 4)
]
internal struct MsgAttachments
{
[MarshalAs(UnmanagedType.I4 )] public Int32 Count;
[MarshalAs(UnmanagedType.SysInt)] public IntPtr Array;
}

[ StructLayout(LayoutKind.Sequential, Pack = 1)
]
internal struct MsgStruct
{
[MarshalAs(UnmanagedType.I8 )] public Int64 Time;
[MarshalAs(UnmanagedType.I8 )] public UInt64 Id;
[MarshalAs(UnmanagedType.I4 )] public MessageType Type;
[MarshalAs(UnmanagedType.Struct)] public MsgAttachments
Attachments;
}

[ StructLayout(LayoutKind.Sequential, Pack = 4)
]
internal struct MsgAttachment
{
public MsgAttachment(AttachmentType T, IntPtr P)
{
Type = T;
Pointer = P;
}

[MarshalAs(UnmanagedType.I4 )] public AttachmentType
Type;
[MarshalAs(UnmanagedType.SysInt)] public IntPtr
Pointer;
}

[ StructLayout(LayoutKind.Sequential, Pack = 4)
]
internal struct AtcString
{
public AtcString(string T)
{
Str = T;
}

[MarshalAs(UnmanagedType.LPWStr)] public string Str;
}

[ StructLayout(LayoutKind.Sequential, Pack = 4)
]
internal struct AtcByteArray
{
public AtcByteArray(Byte[] A)
{
Count = A.Length;
Array = Marshal.AllocHGlobal(Count);

Marshal.Copy(A, 0, Array, Count);
}

[MarshalAs(UnmanagedType.I4 )] public Int32 Count;
[MarshalAs(UnmanagedType.SysInt)] public IntPtr Array;
}

#endregion

#region Constructor / Destructor

public Message(UInt64 Id, MessageType Type)
{
_Msg.Time = DateTime.Now.ToFileTime();
_Msg.Id = Id;
_Msg.Type = Type;

_Msg.Attachments.Count = 0;
_Msg.Attachments.Array =
Marshal.AllocHGlobal(MaxAttachments * Marshal.SizeOf(typeof(Int32)));
}

~Message() { Dispose(); }

#endregion

#region Constants

private const int MaxAttachments = 10;

#endregion

#region Containers

private bool _Disposed = false;

internal MsgStruct _Msg;

#endregion

#region IDisposable

public void Dispose()
{
if (_Disposed) return;

for (Int32 i = 0; i < _Msg.Attachments.Count; ++i)
{
IntPtr p = get_ptr(i);

MsgAttachment atc = (MsgAttachment)ptr_to_struct(p,
typeof(MsgAttachment));

switch (atc.Type)
{
case AttachmentType.Comment:
{
Marshal.DestroyStructure(atc.Pointer,
typeof(AtcString));

break;
}
case AttachmentType.ByteArray:
{
AtcByteArray bytes =
(AtcByteArray)ptr_to_struct(atc.Pointer, typeof(AtcByteArray));

Marshal.FreeHGlobal(bytes.Array);

break;
}
}

Marshal.FreeHGlobal(atc.Pointer);
Marshal.FreeHGlobal(p);
}

Marshal.FreeHGlobal(_Msg.Attachments.Array);

_Disposed = true;
}

#endregion

#region Public Methods

public bool AddComment(string Comment)
{
if (_Disposed || _Msg.Attachments.Count == MaxAttachments)
return false;

add_ptr(struct_to_ptr(new
MsgAttachment(AttachmentType.Comment, struct_to_ptr(new
AtcString(Comment)))));

return true;
}

public bool AddByteArray(Byte[] Array)
{
if (_Disposed || _Msg.Attachments.Count == MaxAttachments)
return false;

add_ptr(struct_to_ptr(new
MsgAttachment(AttachmentType.ByteArray, struct_to_ptr(new
AtcByteArray(Array)))));

return true;
}

public override string ToString() { ... }

#endregion

#region Private Methods

private IntPtr struct_to_ptr(object S)
{
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(S));

Marshal.StructureToPtr(S, p, false);

return p;
}

private object ptr_to_struct(IntPtr P, Type T)
{
return Marshal.PtrToStructure(P, T);
}

private void add_ptr(IntPtr P)
{
Marshal.WriteInt32(
_Msg.Attachments.Array,
_Msg.Attachments.Count * Marshal.SizeOf(typeof(Int32)),
P.ToInt32()
);

_Msg.Attachments.Count++;
}

private IntPtr get_ptr(Int32 I)
{
return new
IntPtr(Marshal.ReadInt32(_Msg.Attachments.Array, I *
Marshal.SizeOf(typeof(Int32))));
}

#endregion
}

#endregion

#region Dll

[DllImport("Logger.dll")] private static extern LogResult
LogOpen([MarshalAs(UnmanagedType.LPWStr)] string Name, ref LogId Id);
[DllImport("Logger.dll")] private static extern LogResult
LogWrite(LogId Id, IntPtr Message);
[DllImport("Logger.dll")] private static extern LogResult
LogClose(LogId Id);

#endregion

#region Constructor / Destructor

public Log(string Name)
{
if (LOG_OK != LogOpen(Name, ref _Id)) throw new
Exception("Failed to open log file.");
}

~Log() { if (_Id != 0) LogClose(_Id); }

#endregion

#region Constants

private const LogResult LOG_OK = 0;

#endregion

#region Containers

private LogId _Id = 0;

#endregion

#region Public Methods

public void Write(Message Msg)
{
try
{
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(Msg._Msg));

Marshal.StructureToPtr(Msg._Msg, p, false);

LogWrite(_Id, p);

Marshal.FreeHGlobal(p);
}
catch (Exception ex)
{
// ... write to event log ...
}
}

#endregion
}

}

In test app it fails on calling LogWrite or in constructor on LogOpen.

The only place were logger.dll is doing something to memory is in
LogOpen returing LogId.

Here is a logger.h (brief):

#include <wtypes.h>

// Enums

enum MessageType { ... };

enum AttachmentType { ... };

// Types

// data

typedef DWORD LOGID, *PLOGID;
typedef DWORD LOGERROR;

typedef ULARGE_INTEGER LOGTIME; // in filetime
format
typedef ULARGE_INTEGER LOGMSGID;

// attachments

typedef struct
{
PCTSTR Text;
}
ATCSTRING;

typedef struct
{
DWORD Count;
BYTE* Array;
}
ATCBYTEARRAY;

// message

typedef struct
{
AttachmentType Type;
void* Pointer;
}
MSGATTACHMENT;

typedef struct
{
DWORD Count;
MSGATTACHMENT** Array;
}
MSGATTACHMENTS;

typedef struct
{
LOGTIME Time;
LOGMSGID Id;
MessageType Type;
MSGATTACHMENTS Attachments;
}
LOGMSG, *PLOGMSG;

typedef const LOGMSG* PCLOGMSG;

// functions

typedef LOGERROR (*PLOGOPEN) (PCTSTR, PLOGID);
typedef LOGERROR (*PLOGWRITE) (LOGID, PCLOGMSG);
typedef LOGERROR (*PLOGCLOSE) (LOGID);
How can the mentioned error happen? And what can i do to avoid it? Any
ideas on possible probblems in interop or logger.dll, maybe i should
set something specific in dll configuration (it was generated as multi-
threaded dll)?

I've read a lot of related topics but still got no clue.

Any help and suggestions would be greatly appreciated.

Thanks.

Feb 6 '07 #1
1 4520
Closed. The problem was caused by static strings in c++ dll.
Feb 6 '07 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Gnanaprakash Rathinam | last post by:
Hi Expert, Is there a way to obtain assembly name in an unmanaged call? During Interop call between managed to unmanaged, I would like to know in unmanaged code about the caller of assembly file...
7
by: Timothy Shih | last post by:
Hi, I am trying to figure out how to use unmanaged code using P/Invoke. I wrote a simple function which takes in 2 buffers (one a byte buffer, one a char buffer) and copies the contents of the byte...
6
by: Eric | last post by:
for example: SqlConnection is used in my project, how can I know if all connections were closed after open and execution. If some guys forget to close connections after using, how can i check it...
5
by: GeRmIc | last post by:
Hi, I am doing an interop from unmanaged code to C#. How do i pass an ArrayList pointer from an unmanaged code, (structres are easily passed by between C# and C). //This is the C code ...
10
by: Mark Jerde | last post by:
I'm trying to learn the very basics of using an unmanaged C++ DLL from C#. This morning I thought I was getting somewhere, successfully getting back the correct answers to a C++ " int SumArray(int...
2
by: joye | last post by:
Hello, My question is how to use C# to call the existing libraries containing unmanaged C++ classes directly, but not use C# or managed C++ wrappers unmanaged C++ classes? Does anyone know how...
1
by: Zapbbx | last post by:
I have a 3rd party application that can reference external dll's. The dll's have to be written in unmanaged code with an exported function I can reference and call. I would like it to call a C# dll...
3
by: Tommy Svensson \(InfoGrafix\) | last post by:
I've been instructed to work againt a huge unmanaged C++ API from a C# application. Now, the only way, as I've understood it, is to go the Managed Extensions for C++ way. This means I have to...
7
by: A n g l e r | last post by:
Hi all. Can you please tell me if you have any problems to use managed C++ DLL libraries that wrap some code from unmanaged external DLL 32 bit libraries? If you called such managed 32 bit DLL...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.