问题 .NET 4:托管代码是否会导致堆损坏?


我的多线程托管程序中存在堆损坏。做一些测试我发现只有当程序中的后台线程处于活动状态时才会发生损坏(它们是可切换的)。线程使用一些第三方组件。

在检查了线程和第三方组件的代码(使用.NET Reflector)后,我发现它们都是托管的,即 没有 “不安全”或“DllImportAttribute”或“P / Invoke”。似乎纯托管代码导致堆损坏,这可能吗?

UPDATE

除了使用Marshal类, 是否有可能在线程未正确同步的情况下破坏堆?一个例子将非常感激。


2398
2017-09-27 18:45


起源

仅仅因为它们都是托管的,并不意味着一切都是线程安全的。您是否确保代码以线程安全的方式执行,使用锁等等? - Chris Dunaway
还有Marshal类方法可以做到这一点。 - Alex F
@ChrisDunaway,你是说不正确的锁定或以非线程安全的方式执行线程可以破坏堆甚至不使用Marshal类?我有一个答案,这是不可能的(这里)。 - net_prog


答案:


绝对有可能在不使用不安全代码的情况下破坏堆。元帅阶级是你的朋友/敌人

IntPtr ptr = new IntPtr(50000);  // Random memory
byte[] b = new byte[100];
Marshalp.Copy(b, 0, ptr, 100);

这有效地将100个连续的0复制到地址50000处的堆中。

另一种方法是使用显式结构布局

[StructLayout(LayoutKind.Explicit)]
struct S1
{
    [FieldOffset(0)]
    internal string str;

    [FieldOffset(0)]
    internal object obj;
}

S1 s = new S1();
s.obj = new Program();
s.str.Trim();  // Hope that works ... :) 

12
2017-09-27 18:55



回覆。结构,共同的 [StructLayout(LayoutKind.Sequential)] 不会导致堆腐败,对吗? - net_prog
@net_prog不, LayoutKind.Explicit 这个技巧需要工作/崩溃:) - JaredPar
@net_prog in 一般 托管代码不可能破坏堆。这些只是一些......可能导致它的极端情况。它的 可能 但你不可能遇到CLR错误。 - JaredPar
你怎么看待最后的回应? 这里? - net_prog
有没有办法在线程未正确同步的情况下执行此操作? - net_prog