2011-03-31 49 views
7

這一個真的讓我難住。我正在和另一位打電話給我的開發者合作,因爲他無法相信他所看到的。我們一起調試了一下,我也看到了,沒有任何解釋。這是場景。他正在寫的是通過一個自動生成的COM包裝第三方COM對象進行交互的方法(通過添加COM組件作爲參考只是產生這是他的方法的頂部:如何設置一個c#方法範圍變量影響另一個?

public bool RefolderDocument(ref IManDocument oDoc) 
    { 
     string strCustom1 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1); 
     string strCustom2 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2); 

的目的代碼是從「文檔」對象(oDoc)中獲取項目編號和子項目編號。

以下是您逐步完成後會發生的情況。第一個分配strCustom1具有預期值「32344」(項目編號)和strCustom2如預期的那樣爲空。第二次分配後,strCustom2獲取子項目編號「0002」 - ,但strCustom1已更改爲32334 - 一個字符r已經改變了!?

它讓我覺得某種古老的c語言堆棧溢出(即使它與COM組件互操作,我也不會期望在託管應用程序中)。我們都很困惑。在試圖破解解決這個bizarreness,我想第一個字符串的內容複製到其他位置,像這樣:

public bool RefolderDocument(ref IManDocument oDoc) 
    { 
     string strCustom1 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)); 
     string strCustom2 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2)); 

相同的結果!在這一點上,我們一直在抓住精力,將代碼從.NET 4移到.NET 3.5(CLR 2),但沒有任何改變。一個可能相關的觀點是,這是一項服務,我們正在關注服務流程。該版本針對x86,並且服務位置肯定位於Debug輸出構建文件夾中。

這是否有任何合理的解釋?我很難理解如何繼續。

回答

1

看起來像strCustom1和strCustom2都被設置爲引用,返回到GetAttributeValueByID的結果。我不知道爲什麼,看看其他人在這裏(派克博士Skeet哈哈......)是否會有意思。

在短期內,雖然,我想你會發現這將解決這個問題你...

public bool RefolderDocument(ref IManDocument oDoc) 
    { 
     string strCustom1 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)); 
     string strCustom2 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2)); 

我的想法基本上是有它計算表達式,而不是與referernce直接工作...

Martin。

Ps。什麼是string.Copy()?

+0

'string.Copy'是他試圖解決這個奇怪的問題... – 2011-03-31 15:47:51

+0

是的。 String.Copy嘗試在源位置被覆蓋之前移動strCustom1實際指向的位置。我預計這會起作用。它沒有。 – 2011-03-31 16:40:15

1

COM對象可能沒有遵循COM內存管理規則,它覆蓋了CLR認爲它擁有的內存。簡單的事情,比如不爲GetEnumerator()創建一個新的對象,真的可以搞砸COM互操作和緩存。

您還必須認識到,COM調用實際上工作的方式是通過爲字符串傳遞對內存的引用。雖然你把它想:

str = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1) 

這真是叫更像:

hresult = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1,&str) 

所以,你可以看到COM對象有一個指針右轉入CLR存儲。

換句話說,看看COM對象,而不是你的.NET代碼。

+0

Tony, 感謝您的回覆。不幸的是,COM對象由供應商擁有,據說經過時間考驗。 :-)。有趣的是在另一個變量中間單個字符的變化!也許其中一個建議的解決方法將成功。 – 2011-03-31 16:39:13

+1

@Decker,是的,這是不幸的。我遇到了很多「經過時間考驗」的COM DLL在.NET下失敗的問題,因爲它們不遵循COM interop期望的規則。如果我實現了複製變通方法,我會害怕內存損壞 - 如果幸運的話,這只是一個調試器問題(我只在C++中看到過,而不是.NET,但還有一些是報告.NET)。我建議嘗試動態類型,如果您使用.NET 4.0並通過ole自動化,但需要首先理解已更改數據的來源。 – 2011-03-31 20:56:50

0

我不確切知道爲什麼會發生這種情況,我希望有人隨同答案。作爲解決方案我會解析返回的字符串到一個int然後執行第二個語句。至少可以解決丟失的價值問題。

int Custom1 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)); 
int Custom2 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2)); 
1

我遇到一個看起來類似於你所描述的一個問題。

我的情況,.NET /編譯器/ runtine/CLR工作得很好,唯一的問題是Visual Studio調試器顯示不正確的值。嘗試編寫你的值,例如到System.Diagnostics.Trace或控制檯,檢查這是否是您的情況。

+0

這很吸引人。我不認爲*是這種情況,因爲它看起來好像價值確實發生了變化。事實上,我們仔細檢查這段代碼的方式是因爲一些審計代碼檢測到了差異。但將它拋出到Trace以確認它不是調試器顯示問題並不會造成傷害。 – 2011-03-31 16:42:25

+0

這也是我的猜測。在每個點上將這些值寫入日誌,並以這種方式進行分析。我看不到如何*複製*字符串可以改變。 – 2011-03-31 16:53:57

相關問題