小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

c# – Finalizer在其對象仍在使用時啟動

 印度阿三17 2019-07-13

簡介:C#/ .NET應(yīng)該是垃圾回收. C#有一個析構(gòu)函數(shù),用于清理資源.當(dāng)一個對象A被垃圾收集在同一行我試圖克隆其變量成員之一時會發(fā)生什么?顯然,在多處理器上,有時,垃圾收集器贏了……

問題

今天,在關(guān)于C#的培訓(xùn)課程中,老師向我們展示了一些僅在多處理器上運行時才包含錯誤的代碼.

我將總結(jié)一下,有時候,編譯器或JIT通過在從被調(diào)用方法返回之前調(diào)用C#類對象的終結(jié)器來搞砸.

Visual C 2005文檔中給出的完整代碼將作為“答案”發(fā)布,以避免提出非常大的問題,但必要的內(nèi)容如下:

以下類具有“Hash”屬性,該屬性將返回內(nèi)部數(shù)組的克隆副本.在構(gòu)造中,數(shù)組的第一項值為2.在析構(gòu)函數(shù)中,其值設(shè)置為零.

關(guān)鍵是:如果你試圖得到“示例”的“哈?!睂傩?你將獲得一個干凈的數(shù)組副本,其第一個項目仍然是2,因為正在使用該對象(因此,不是垃圾收集/定稿):

public class Example
{
    private int nValue;
    public int N { get { return nValue; } }

    // The Hash property is slower because it clones an array. When
    // KeepAlive is not used, the finalizer sometimes runs before 
    // the Hash property value is read.

    private byte[] hashValue;
    public byte[] Hash { get { return (byte[])hashValue.Clone(); } }

    public Example()
    {
        nValue = 2;
        hashValue = new byte[20];
        hashValue[0] = 2;
    }

    ~Example()
    {
        nValue = 0;

        if (hashValue != null)
        {
            Array.Clear(hashValue, 0, hashValue.Length);
        }
    }
}

但沒有什么是這么簡單……
使用這個類的代碼是在一個線程內(nèi)部進(jìn)行的,當(dāng)然,對于測試,該應(yīng)用程序是多線程的:

public static void Main(string[] args)
{
    Thread t = new Thread(new ThreadStart(ThreadProc));
    t.Start();
    t.Join();
}

private static void ThreadProc()
{
    // running is a boolean which is always true until
    // the user press ENTER
    while (running) DoWork();
}

DoWork靜態(tài)方法是問題發(fā)生的代碼:

private static void DoWork()
{
    Example ex = new Example();

    byte[] res = ex.Hash; // [1]

    // If the finalizer runs before the call to the Hash 
    // property completes, the hashValue array might be
    // cleared before the property value is read. The 
    // following test detects that.

    if (res[0] != 2)
    {
        // Oops... The finalizer of ex was launched before
        // the Hash method/property completed
    }
}

每隔1,000,000個DoWork提供一次,顯然,垃圾收集器會發(fā)揮其魔力,并試圖回收“ex”,因為它不再在函數(shù)的重新編寫代碼中引用,而這次,它比“哈?!备斓玫椒椒?所以我們最終得到的是一個零ed字節(jié)數(shù)組的克隆,而不是正確的一個(第一項為2).

我的猜測是代碼的內(nèi)聯(lián),它基本上取代了DoWork函數(shù)中標(biāo)記為[1]的行:

    // Supposed inlined processing
    byte[] res2 = ex.Hash2;
    // note that after this line, "ex" could be garbage collected,
    // but not res2
    byte[] res = (byte[])res2.Clone();

如果我們認(rèn)為Hash2是一個簡單的訪問器,編碼如下:

// Hash2 code:
public byte[] Hash2 { get { return (byte[])hashValue; } }

所以,問題是:這應(yīng)該在C#/ .NET中以這種方式工作,還是可以認(rèn)為這是JIT編譯器的錯誤?

編輯

有關(guān)解釋,請參閱Chris Brumme和Chris Lyons的博客.

http://blogs./cbrumme/archive/2003/04/19/51365.aspx
http://blogs./clyon/archive/2004/09/21/232445.aspx

每個人的回答都很有趣,但我不能選擇一個比另一個好.所以我給了你一個1 …

抱歉

??

編輯2

我無法在Linux / Ubuntu / Mono上重現(xiàn)問題,盡管在相同條件下使用相同的代碼(同時運行多個相同的可執(zhí)行文件,發(fā)布模式等)

解決方法:

它只是代碼中的一個錯誤:終結(jié)器不應(yīng)該訪問托管對象.

實現(xiàn)終結(jié)器的唯一原因是釋放非托管資源.在這種情況下,您應(yīng)該仔細(xì)實施the standard IDisposable pattern.

使用此模式,您可以實現(xiàn)受保護的方法“protected Dispose(bool disposing)”.從終結(jié)器調(diào)用此方法時,它會清除非托管資源,但不會嘗試清理托管資源.

在您的示例中,您沒有任何非托管資源,因此不應(yīng)該實現(xiàn)終結(jié)器.

來源:https://www./content-1-322801.html

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多