日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

那些年,我在游戏开发中改过的bug:靠不住的OS和SDK

發(fā)布時(shí)間:2024/8/26 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 那些年,我在游戏开发中改过的bug:靠不住的OS和SDK 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

記憶中有很多次了,幾個(gè)程序員朋友聊天,聊著聊著,就聊到自己遇到過的bug。然后大家開始口沫橫飛交流那些或詭異或神奇的bug,談?wù)撟约寒?dāng)年是如何搞定bug或是被bug搞定。

正好看見Gamesutra上也登了篇Dirty Coding Tricks ,發(fā)現(xiàn)老外也有這個(gè)癖好,原來天下程序員本一家。一路走來,程序員的成長,便是一路刀光劍影,與bug斗個(gè)你死我活。了解別人的Debug過程,或是回憶一下自己Debug的時(shí)候思路,也是很有意思的事情,值得定期總結(jié)。

下面分享一下自己遇到過印象深刻的bug:

靠不住的c:Memcpy的傳說

做一個(gè)PC項(xiàng)目的時(shí)候,兇猛的測試兄弟把Winxp 64單獨(dú)列出來,作為一個(gè)測試平臺(tái),然后我們的噩夢就開始了。游戲在Winxp 64上面頻繁Crash,經(jīng)常在更新Octree的時(shí)候訪問到空指針,但邏輯上來看那個(gè)指針不可能是空的。Crash位置很隨機(jī),到處都有,通常都是玩了一個(gè)小時(shí)在一個(gè)莫名其妙的地方Crash。

第一反應(yīng)就是那些地址被非法訪問,可能是某個(gè)錯(cuò)誤的指針指向那里,往里面寫了不該寫的值。于是我根據(jù)最常Crash的地址設(shè)下數(shù)據(jù)斷點(diǎn),試了好幾天,從來沒有斷下過,Crash還是依舊。然后同事試圖加上大量的保護(hù)代碼,判斷一個(gè)指針是不是空指針后才使用,很好的降低了Crash機(jī)率,但偶爾還是會(huì)有。想想問題根源沒有找到,降低Crash概率只是讓自己更難修bug,而且訪問Octree也比較多,亂加保護(hù)會(huì)影響性能,我一狠心又把保護(hù)代碼全去掉了。
?

Takeaway: 不到萬不得已,不要用保護(hù)代碼掩蓋Bug,它知會(huì)讓你的日子更難過。


來回幾輪搞下來,根據(jù)某次比較靠譜的Crash Callstack,懷疑到了memcpy。memcpy是個(gè)老同志了,兢兢業(yè)業(yè)地忙碌在各個(gè)程序里,負(fù)責(zé)搬運(yùn)數(shù)據(jù)很多年,工作績效有口皆碑。它有什么問題呢?它還能有什么問題呢?

為了保證多線程能同步并行執(zhí)行,我們程序中有個(gè)很大的memcpy,把一塊Octree從后臺(tái)用memcpy復(fù)制到前臺(tái)的工作buffer。當(dāng)然這個(gè)做法的設(shè)計(jì)優(yōu)劣不在此討論,存在即合理,2007年,多線程引擎我們還不是那么擅長搞。

既然有懷疑,就要捉奸。我做了試驗(yàn),在memcpy后面直接加一個(gè)循環(huán),逐字節(jié)比較源數(shù)據(jù)和目標(biāo)數(shù)據(jù),有時(shí)候居然會(huì)不相等... 這個(gè)可顛覆了我的世界觀。我試圖寫了一個(gè)函數(shù),里面就一個(gè)循環(huán),逐字節(jié)復(fù)制數(shù)據(jù),然后把所有的memcpy全替換成這個(gè)函數(shù),果然不Crash了。但顯然這是不行的,速度太慢了。

既然有了點(diǎn)線索,就可以試圖簡化bug重現(xiàn)條件了。我不能每次都花一個(gè)小時(shí)去運(yùn)行游戲,尋找那一次crash。我在游戲load起來,開始走主循環(huán)后,加了一個(gè)死循環(huán),不停用memcpy復(fù)制一塊內(nèi)存,然后比較源數(shù)據(jù)和目標(biāo)數(shù)據(jù)。源數(shù)據(jù)里面沒有0,都是1-255的值,可是運(yùn)行幾十秒以后目標(biāo)數(shù)據(jù)居然有0。這樣,我們成功地把重現(xiàn)一次bug的平均時(shí)間從一個(gè)小時(shí)降低到一分鐘。

我們的懷疑從3d代碼轉(zhuǎn)移到多線程,在進(jìn)入那個(gè)死循環(huán)之前,我們設(shè)下斷點(diǎn),把其他無關(guān)的線程全部都Freeze,只有那個(gè)線程會(huì)運(yùn)行。這樣,任何多線程的干擾全部排除,memcpy在一個(gè)理想的環(huán)境中歡快的運(yùn)行,但memcpy還是會(huì)出錯(cuò)。

繼續(xù)簡化,我單獨(dú)寫一個(gè)小程序,里面只做死循環(huán)和memcpy,游戲賬號(hào)交易平臺(tái)來判斷是不是OS的問題(實(shí)在是走投無路了)。試驗(yàn)結(jié)果是,Winxp 64沒有問題,memcpy始終如一地正常工作著(本該如此^_^)。 可是某一次,當(dāng)我們的游戲在后臺(tái)運(yùn)行的時(shí)候,再啟動(dòng)這個(gè)小程序,居然memcpy又出問題了...無語了,原來我們的游戲還能萬里追殺,跨進(jìn)程搞垮OS下面的其他進(jìn)程。

山窮水盡疑無路,我無奈下單步跟蹤了一下memcpy的匯編代碼,上來有兩句

  • cmp DWORD PTR __sse2__available,0
  • je Dword_align
  • 復(fù)制代碼


    也就是說,memcpy上來看有沒有設(shè)置__sse2_available,這個(gè)值估計(jì)是CRT庫里面設(shè)的,如果有SSE2就執(zhí)行sse優(yōu)化的memcpy,沒有就跳到Dword_align那里執(zhí)行普通版本的流程。我開始懷疑是不是我們的游戲里面對系統(tǒng)做了點(diǎn)什么手腳,導(dǎo)致在__sse2_available允許的情況下,優(yōu)化的代碼會(huì)執(zhí)行出錯(cuò)。游戲的代碼規(guī)模實(shí)在太大,又用了n個(gè)中間件,我無力一一查看,且我也看不懂SSE代碼(哎呀好羞射),就隨手做了個(gè)試驗(yàn),在那句判斷的地方,通過Debugger把__sse2_available的值改成了0。從此memcpy再也不出錯(cuò)了。

    所以最終的解決方案是,Win64下,我在游戲一開始初始化的地方,加上謎一樣的初始化代碼:
    ?

  • extern "C" extern DWORD __sse2_available;
  • __sse2_available = 0;
  • 復(fù)制代碼


    這樣memcpy就永遠(yuǎn)使用不做sse2優(yōu)化的代碼了。

    memcpy不使用sse2后會(huì)不會(huì)有性能問題?經(jīng)過測試,發(fā)現(xiàn)問題不大,對于頻繁調(diào)用的少量數(shù)據(jù)復(fù)制,memcpy不太能從sse2里面得到多少好處。對于大量數(shù)據(jù)的復(fù)制,我們用得也不多,profile了一下,沒有發(fā)現(xiàn)明顯的瓶頸,無視了。這事情也可以從反向理解,由于游戲規(guī)模太大,各種多線程和GPU/CPU同步,導(dǎo)致任何一點(diǎn)的效率損失,可能不會(huì)擴(kuò)散到整個(gè)游戲,被其他同步和等待吸收掉了…我真是一個(gè)好程序員,能想到這么好的理由說服自己。

    對游戲跨進(jìn)程影響其他程序的memcpy,實(shí)在沒能力解決了,Winxp 64是一個(gè)太小眾的環(huán)境,用戶要么用Winxp 32, 要么用Vista 32/64,市場占有率很低,我們也算仁至義盡了。

    可得結(jié)論:Winxp 64靠不住(其實(shí)問題還是應(yīng)該出在我們內(nèi)部,不過其他OS都沒問題,就賴在它身上了)
    ?

    Takeaway: 首先,你要有一個(gè)有耐心的老板,才能給你時(shí)間去查這么奇怪的Bug


    為了達(dá)成目的,我們要不擇手段。

    靠不住的SDK:OutputDebugString

    話說當(dāng)年開發(fā)Splinter Cell 4,使用的還是XBOX360的Alpha kit。微軟早期的360 Kit,全不像后期的Kit,后期kit長得和主機(jī)差不多。而當(dāng)時(shí)的KIt,是用一個(gè)很大的Power Mac G5,換上一塊ATI顯卡,再刷上MS的固件,連馬甲都不穿一件就出來見人了。

    Xbox 360開發(fā)SDK,早期bug一大堆,比如預(yù)編譯頭文件太大了,編譯器抱怨說預(yù)編譯頭文件預(yù)留內(nèi)存不夠,這個(gè)好辦,加上/Zm512編譯選項(xiàng)即可。加上,編譯,沒用?!只好寫信去MS問,他們說,哦,原來如此啊,今天天氣真好,哈哈哈哈,請等待下一次更新,謝謝您匯報(bào)云云...雖是MS的bug,可是我也不能等著他修復(fù)才工作,只好手動(dòng)拆分預(yù)編譯頭文件,把很多內(nèi)容放在預(yù)編譯頭文件外面,預(yù)編譯頭文件就會(huì)變小,編譯就可以順利通過了。

    扯遠(yuǎn)了,回頭來說這個(gè)OutputDebugString的問題。

    360有3個(gè)cores,每個(gè)core有2個(gè)Hyperthreads,總計(jì)6個(gè)線程,我們的游戲在邏輯線程、聲音線程和渲染線程外,還開了3個(gè)輔助線程,用自己寫的Thread Pool管理系統(tǒng)來管理這些線程,初始化的時(shí)候就是一個(gè)循環(huán)把每個(gè)線程創(chuàng)建出來。

    這個(gè)bug的表現(xiàn)現(xiàn)象就是加載失敗,程序僵死。團(tuán)隊(duì)當(dāng)時(shí)有幾十個(gè)測試人員,每天打游戲八小時(shí),從沒碰到過游戲加載失敗情況。但是開發(fā)人員這里就有很低概率會(huì)加載失敗,表現(xiàn)情況為用VC啟動(dòng)游戲,然后過一會(huì)加載屏幕就僵死不動(dòng)了。開發(fā)人員往往過了5分鐘還沒在電視上看見游戲畫面才知道游戲又掛了,重現(xiàn)概率是每個(gè)程序員每一到兩天碰到一次。我們擔(dān)心這是線程管理系統(tǒng)內(nèi)部的問題,就讓每個(gè)開發(fā)人員碰到這種情況不要急著重啟動(dòng),把現(xiàn)場給我看一下。每次僵死的時(shí)候都是在系統(tǒng)內(nèi)核死鎖,Callstack也沒有有價(jià)值的信息,基本都是在創(chuàng)建每個(gè)線程的時(shí)候打印一句語句的時(shí)候就內(nèi)核就死了。在接下來一周里,我試圖在線程管理系統(tǒng)內(nèi)部加一些日志輸出,每次重現(xiàn)bug的時(shí)候查看日志,也沒有找到更好的線索。

    重現(xiàn)概率實(shí)在太低,不好調(diào)試,于是我試圖用簡單的程序片段來重現(xiàn)這個(gè)bug。因?yàn)槎际莿?chuàng)建新線程時(shí)候死鎖,第一個(gè)想到的就是寫一個(gè)小程序,直接一個(gè)死循環(huán),創(chuàng)建線程,打印日志,然后殺掉線程,重復(fù)再做。果然能夠重現(xiàn)bug,程序運(yùn)行1分鐘以后,就死鎖了。同樣的現(xiàn)場,還是在OutputDebugString內(nèi)部死鎖了。難道bug不是在線程庫,而是在OutputDebugString內(nèi)?
    ?

    Takeaway: 不要輕易相信你看見的表層問題,問題可能在別處


    正好那些天有個(gè)微軟360開發(fā)組的人員在我們組Onsite支持,于是他帶著大量的360 Sdk的符號(hào)庫(Symbol)來幫助調(diào)試,因?yàn)樗皇亲鲞@一個(gè)模塊的,最后也沒有什么結(jié)果。最后他把我的小程序發(fā)回微軟,找到內(nèi)部開發(fā)人員處理,這比我們直接走正式support流程快很多。
    ?

    Takeaway: 隔離問題,編寫更小的測試案例,便于和別人溝通交流,尋求幫助


    一天后,微軟發(fā)回Email,說這是內(nèi)部的Bug,請無視,不會(huì)影響Release版本,是Debug協(xié)議上的問題。

    可得結(jié)論:微軟靠不住。

    總結(jié)

    以上是生活随笔為你收集整理的那些年,我在游戏开发中改过的bug:靠不住的OS和SDK的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 天堂中文在线最新 | 亚洲欧美精品aaaaaa片 | 私密spa按摩按到高潮 | 日本大乳美女 | 91官网视频 | 中国一级大黄大黄大色毛片 | 中国美女毛片 | 国产xxxx性hd极品 | 日本在线一级 | 久久久久这里只有精品 | 日本黄动漫 | 亚洲精品高清视频 | 国产伦理一区二区三区 | 国产91边播边对白在线 | 娇妻被老王脔到高潮失禁视频 | 一区二区三区精品国产 | 色多多视频在线观看 | 国产午夜精品理论片 | 成人综合影院 | 黄色专区 | 欧美涩涩视频 | 17c一起操 | 中文字幕日韩精品无码内射 | 国产性猛交普通话对白 | 九九热在线观看视频 | av解说在线| 亚洲理论电影在线观看 | 污的网站| 亚洲三级久久 | 青草视屏 | 91麻豆精品国产91久久久更新时间 | 五月精品 | 中文字幕制服丝袜 | 日韩久久影视 | 亚洲国产精品无码专区 | 最近日韩中文字幕中文 | 日本夜夜操| 羞羞网站在线看 | 精品久久久久久一区二区里番 | 国产又粗又猛又爽又黄的视频在线观看动漫 | 免费看国产精品 | 欧美在线免费观看 | 污污软件在线观看 | 蜜臀精品 | 精品三级视频 | 国产亚洲精品电影 | 欧美 亚洲 激情 一区 | 欧美日批| 91香蕉国产| 欧美三级中文字幕 | 中文字幕人妻熟女人妻a片 麻豆91视频 | 中文字幕在线观看日本 | 一本毛片 | av一起看香蕉 | 亚洲精品五月 | 国产天堂一区 | 冈本视频在线观看 | www.999av| 污污网站在线免费观看 | 在线观看免费看片 | 国产做爰全过程免费视频 | 在线免费看毛片 | 高潮无码精品色欲av午夜福利 | 性色欲网站人妻丰满中文久久不卡 | 一级全黄色片 | 日韩影音| 色久在线| 17c国产精品 | 优优色影院 | 91尤物国产福利在线观看 | 欧美乱视频 | 欧美88av | 色美av | 91在线综合 | 根深蒂固在线观看 | 日本成人精品 | 国内精品人妻无码久久久影院蜜桃 | 天天色影综合网 | 欧美日韩v | 中国一级黄色大片 | 亚洲高清在线 | 亚州av综合色区无码一区 | 国产黄色av | 中国美女洗澡免费看网站 | 啪啪av网站 | 天天干天天色天天 | 男男巨肉啪啪动漫3d | 国产精品一区二区视频 | 日本高清免费观看 | 打屁股无遮挡网站 | 欧美成人猛片aaaaaaa | 国产日韩欧美日韩大片 | 国产黄色网 | 亚洲av永久中文无码精品综合 | 色综合久久久久综合体桃花网 | 国内三级在线 | 欧美在线视频一区 | 人妻无码久久精品人妻 | 日本一区二区三区免费看 |