Вот мой код:
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);
}
А вот и структура:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct EDITBALLOONTIP
{
internal int cbStruct;
internal string pszTitle;
internal string pszText;
internal int ttiIcon;
}
Почему это прекрасно работает в Windows XP + .NET 3.5 и вызывает исключения в Windows 7 + .NET 4.0? Может быть, это проблема CharSet?
===================== решаемые =================== ====
Решение и объяснение
Как видите, Marshal.StructureToPtr (ebt, ptrStruct, true ); для третий параметр имеет значение true. Это означает, что система попытается освободить последнюю выделенную память для ptrStruct. Но когда метод Show()
вызывается впервые, для этой структуры не было выделено памяти (ptrStruct = IntPtr.Zero). Таким образом, система попытается освободить память, расположенную в нулевом указателе. И, конечно, это вызовет исключение. Windows XP просто игнорирует это, а Windows 7 - нет.
И вот лучшее решение ИМХО:
Marshal.StructureToPtr(ebt, ptrStruct, false);
//Working...
//Free resources
Marshal.FreeHGlobal(ptrStruct);