Here is my code:
internal void Show()
{
if (Parent == null)
throw new NullReferenceException();
EDITBALLOONTIP ebt = new EDITBALLOONTIP();
ebt.cbStruct = Marshal.SizeOf(ebt);
ebt.pszText = Text;
ebt.pszTitle = Caption;
ebt.ttiIcon = (int)Icon;
IntPtr ptrStruct = Marshal.AllocHGlobal(Marshal.SizeOf(ebt));
Marshal.StructureToPtr(ebt, ptrStruct, true); // Here we go.
// Access violation exception in Windows 7 + .NET 4.0
// In Windows XP + .NET 3.5, it works just fine.
// ... Some other code ...
Marshal.FreeHGlobal(ptrStruct);
}
And here is the structure:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct EDITBALLOONTIP
{
internal int cbStruct;
internal string pszTitle;
internal string pszText;
internal int ttiIcon;
}
Why does this work fine in Windows XP + .NET 3.5 and raises exceptions in Windows 7 + .NET 4.0? May be it's CharSet trouble?
=====================Solved=======================
Solution and explanation
As you can see Marshal.StructureToPtr(ebt, ptrStruct, true); has third parameter set to true. It means that the system will try to free the last allocated memory for ptrStruct. But when method Show()
is invoked for the first time, there was not allocated memory for that structure (ptrStruct = IntPtr.Zero). So system will try to free memory located at zero pointer. And of course it will raise an exception. Windows XP just ignores this, but Windows 7 doesn't.
And here is best solution IMHO:
Marshal.StructureToPtr(ebt, ptrStruct, false);
//Working...
//Free resources
Marshal.FreeHGlobal(ptrStruct);