如果你是c++程式設計師,我想你可能遇到過這樣的情況:
在debug時,對著乙個函式step into,明明呼叫的是a函式,可是結果卻跳進了b函式。
為什麼,call stack裡顯示的也是明明白白,就是直接進了b函式。百思不得其解,於是你懷疑是不是系統出了問題,是不是編譯器出了問題,是不是偵錯程式出了問題~~~
其實那些玩意不是那麼容易出錯的,先看看你你的a,b函式是不是同乙個類的虛函式,如果是,這極有可能是因為你修改過虛函式而沒有完全編譯引起的。
還沒明白?看看這個例子, 假設你在project1中有乙個名為debuggingnow的類,該類有三個虛函式:
在project2中你呼叫了其虛函式:class debuggingnow
;
pdbgnow->f2();
之後由於某種需求你在這個類中加入了乙個虛函式:
class debuggingnow
;
pdbgnow->f2()之前被編譯為呼叫類debuggingnow的第二個虛函式,因為是虛函式,其真正呼叫類似於pdbgnow->vtable[1]。因為在加入函式f1_5()後,f1_5成為了該虛表中的第二個函式,但由於沒有重新編譯project2,pdbgnow->f2()的呼叫沒有更新為正確的pdgbnow->vtable[2],所以真正呼叫的是函式f1_5(),與函式名無關。可能你會認為這種"低階錯誤"根本不會發生在你身上,至少有兩個方法來解決這個問題:
永遠把虛函式加到最後
永遠編譯所有的工程
的確,這兩招在一定程度上是有效的,但讓我們仔細分析一下:
永遠把虛函式加到最後,針對上面這個例子是有用的。可是如果有其他類派生於類debuggingnow,即使你把虛函式加到了類debuggingnow的最後,還是會打亂其派生類的虛表。
永遠編譯所有的工程,這的確是乙個保險的方法。可是在乙個大型系統中,編譯所有的**所耗費的時間是非常大的,加了乙個虛函式,你可能得等上個好幾個小時才能看到最後的結果,這是我們不願承受的。
那麼,對於大型系統中乙個正處於積極修改期的核心基類,乙個比較好的操作方法是預先分配好足夠多的虛函式,這樣之後需要加虛函式是,只要修改乙個原有的就行了,無需大規模的rebuild ,只需編譯一下用到了這個虛函式的**就可以了。可以說節省的時間是相當可觀的:
只要靈活運用dummyvirtualfunction,你不光可以運用於加虛函式,也可以在刪虛函式時發揮其作用。class debuggingnow
;
記住兩個操作原則:
當dummyvirtualfunction快用完時,再預先分配一些。
當這一階段開發結束時,該基類趨於穩定,把多餘的dummyvirtualfunction去掉就可以了。
SPI匯流排那點破事
spi為序列外設介面的縮寫,spi為高速全雙工同步通訊匯流排,共使用4根線。spi以主從方式工作,通常可以乙個主裝置和乙個或多個從裝置。需要至少4根線。miso 主裝置資料輸入 mosi 主裝置資料輸出 sclk 時鐘 cs 片選 cs是從裝置是否被主裝置選中的引腳,當被選中時 通常以cs為低電平選...
談談VIP漂移那點破事
一直以來都是用nginx的upstream模組做 最前端的負載均衡,為了防止nginx本身宕機導致 不能訪問,通常都會做兩套nginx反向 然後用keepalive之類的軟體提供vip。常見的環境是nginx主節點和從節點各有乙個公網ip,乙個私有ip,vip位址也使用公網ip來提供,正常情況下vi...
談談VIP漂移那點破事
一直以來都是用nginx的upstream模組做 最前端的負載均衡,為了防止nginx本身宕機導致 不能訪問,通常都會做兩套nginx反向 然後用keepalive之類的軟體提供vip。常見的環境是nginx主節點和從節點各有乙個公網ip,乙個私有ip,vip位址也使用公網ip來提供,正常情況下vi...