1

I am using Trhird party tool in my application. On some systems i get the System.AccessViolation error. Although, through code i am not able to reproduce the issue. But in the production environment it does reproduce at some time.

I have the doubt on the following code

public static IntPtr TestMarshalToPointer(object value, System.Type type, int length)
{
    int offset = 0;
    int size = Marshal.SizeOf(type) * length;
    IntPtr buffer;

    try
    {
        buffer = Marshal.AllocHGlobal(size);

        for (var index = 0; index < length; index++)
        {
            Marshal.StructureToPtr(value, new IntPtr(buffer.ToInt32() + offset), false);
            // Its written on MSDN that passing false can lead to memory leak. Please guide , should i need to pass true and how it will affect**
            offset += Marshal.SizeOf(type);
        }
    }
    catch
    {
        buffer = (IntPtr)null;
    }

    return buffer;
}
Serj-Tm
  • 16,581
  • 4
  • 54
  • 61
Learner
  • 1,490
  • 2
  • 22
  • 35

3 Answers3

3

Not really an answer as much as some observations, but it got too long for a comment, so:

  1. If you want to return an IntPtr that represents null, use IntPtr.Zero; that's its entire purpose.

  2. The IntPtr class has an Add method that adds an offset to an existing IntPtr, which is safer than what you're doing.

  3. Since you just allocated your global buffer, and it has no managed reference in it yet, you should continue to pass false to StructureToPtr; there's nothing for it to free, in any case

Can you tell exactly which line of this code is producing the access violation?

Michael Edenfield
  • 28,070
  • 4
  • 86
  • 117
  • Thanks Michael for ur valuable inputs..the logging shows the messages till the for loop (e.g. for (var index = 0; index < length; index++)) and then it throws the AccessVioation (Although, not sure b'coz no more logging statements after that, so will put some more of them) ..i have used HandleProcessCorruptedStateExceptions to handle this..it does not throw the exception from the method i've provided , its throwing from the public method where i've kept the HandleProcessCorruptedStateExceptions attribute...any comment on this? – Learner Mar 28 '12 at 05:39
  • In .NET 4, only methods that indicate they can handle corrupted state exceptions will ever get them; if you have such methods in the middle level of a call stack, it will appear as if the exception is being thrown in that method regardless of how deep it actually got thrown. You can turn off this behavior by using the legacy corrupted state exception policy, which might help you debug your problem: http://msdn.microsoft.com/en-us/library/dd638517.aspx – Michael Edenfield Mar 29 '12 at 14:31
2

I'm not sure what is causing the access violation, but this line:

Marshal.StructureToPtr(value, new IntPtr(buffer.ToInt32() + offset), false);

Seems suspicious. Replacing the code with smarter use of the IntPtr class might help:

buffer = Marshal.AllocHGlobal(size);
offset = buffer;
for (var index = 0; index < length; index++)
{
    Marshal.StructureToPtr(value, offset, false);
    IntPtr.Add(offset, Marshal.SizeOf(type));
}
Ritch Melton
  • 11,498
  • 4
  • 41
  • 54
  • Thanks Ritch and Michael for your valuable inputs, i will certainly try this but i am unable to reproduce it from the Debug mode so need to check it in the production environment with these changes ...I have used HandleProcessCorruptedStateExceptions inorder to catch the exception...any comment on this? – Learner Mar 28 '12 at 05:35
  • The structure which i am Marshlling is this : [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct MyStructure – Learner Mar 28 '12 at 05:45
0

Are you running on 64 bit? The following code will, of course, fail: buffer.ToInt32()

You should also call FreeHGlobal after you are done with the buffer. Leave the param as false.

usr
  • 168,620
  • 35
  • 240
  • 369