當你運作一段代碼、一個軟體,在運作時你發現:debug下正常, release下f5運作也正常,唯獨release編繹後單獨運作異常,你會怎麼想?
這個問題對我而言,腦海裡不曾有過,于是蛋定思蛋,先百度了一下:發現網上資訊并不多,偶爾幾條也是vc++的,對于c#的,絕無僅無。

當我把代碼發給一友人,讓他也幫忙試下時,發現對方的win7 64位竟然運作正常,靈異性又提升了一個等級。
面對這神一般的靈異bug,我費了n個小時折騰,找一個不能調試的bug,因為f5下都是正常的,那個辛苦啊。
靈異現象已經說了,那靈異點是什麼呢?标題已經出賣了這個問題,和aop的realproxy有關。
光說aop,園子裡懂的人不多,用的估計也不多,是以深入無謂,淺出又難,隻好簡單過過場。
我是怎麼發現問題是在aop realproxy?
這個使用正常方法,在代碼段裡插一些彈出資訊,來縮小出錯的代碼片斷,最終找到了它。
為了減少廢話,這裡直接講述兩點:
1:哪些代碼有問題,哪裡有問題?
這裡給出詳細的錯誤代碼,和注釋錯誤點,代碼通常都有點長,不容易看:
using system;
using system.reflection;
using system.runtime.remoting.activation;
using system.runtime.remoting.messaging;
using system.runtime.remoting.proxies;
internal class aopattribute : proxyattribute
{
public override marshalbyrefobject createinstance(type servertype)
{
aopproxy proxy = new aopproxy(servertype);
return (proxy.gettransparentproxy() as marshalbyrefobject);
}
}
internal class aopproxy : realproxy
public aopproxy(type servertype) : base(servertype)
public override imessage invoke(imessage msg)
imessage message3;
if (msg == null)
{
return msg;
}
if (msg is iconstructioncallmessage)
iconstructionreturnmessage message = base.initializeserverobject((iconstructioncallmessage) msg);
realproxy.setstubdata(this, message.returnvalue);
return message;
if (!(msg is imethodcallmessage))
imethodcallmessage mcm = msg as imethodcallmessage;
try
object[] args = mcm.args;
message3 = new returnmessage(mcm.methodbase.invoke(base.getunwrappedserver(), args), args, args.length, mcm.logicalcallcontext, mcm);
catch (exception exception)
throw new exception(exception.message);
return message3;
[aopattribute]
public class users : contextboundobject
public users()
int i = 0;//任何的成員變量,在被aop調用的時候,都會報“未将對象引用到對象執行個體的錯誤”
public void test()
i = 1;
catch (exception err)
system.windows.forms.messagebox.show(err.message);
通常大量的代碼測試及分析方法,我發現了,隻要aop對象涉及到内部成員變量,在release編繹後運作就一定會報錯。
2:如何解決。
在曆經各種無解後,我發現了,realproxy還有另一種寫法,而這另一種寫法,竟然可以解決這個問題,代碼如下:
class aopattribute : proxyattribute
aopproxy realproxy = new aopproxy(servertype, base.createinstance(servertype));
return realproxy.gettransparentproxy() as marshalbyrefobject;
class aopproxy : realproxy
methodinfo method;
marshalbyrefobject _target = null;
public aopproxy(type servertype,marshalbyrefobject target)
: base(servertype)
_target = target;
method = servertype.getmethod("set", bindingflags.nonpublic | bindingflags.instance);
if (msg != null)
if (msg is iconstructioncallmessage)
{
iconstructioncallmessage constructcallmsg = msg as iconstructioncallmessage;
realproxy defaultproxy = remotingservices.getrealproxy(_target);
//如果不做下面這一步,_target還是一個沒有直正執行個體化被代理對象的透明代理,
//這樣的話,會導緻沒有直正建構對象。
defaultproxy.initializeserverobject(constructcallmsg);
//本類是一個realproxy,它可通過gettransparentproxy函數得到透明代理
return system.runtime.remoting.services.enterpriseserviceshelper.createconstructionreturnmessage(constructcallmsg, (marshalbyrefobject)gettransparentproxy());
}
else if (msg is imethodcallmessage)
imethodcallmessage callmsg = msg as imethodcallmessage;
object[] args = callmsg.args;
//system.windows.forms.messagebox.show(callmsg.methodbase.tostring());
if (callmsg.methodname.startswith("set_") && args.length == 1)
{
method.invoke(_target, new object[] { callmsg.methodname.substring(4), args[0] });//對屬性進行調用
}
return remotingservices.executemessage(_target, callmsg);
return msg;
3:debug和release還有f5,究竟隐藏怎樣的秘密?
我也不懂,這涉及更底層的問題,不在我深究的範圍内,懂的人士可以留言給大夥解答下。
總結:
在程式設計的世界裡,靈異總是無處不在的,但是找它靈異的原因,并且能找到一種解決這類事件的方法,是每個代碼建造師必須具有能力。
至于為何會産生這樣那樣的靈異事件,在研究的範圍内,可以追究原因,在非自身研究的領域,大夥看着辦了。