| 6 | 1/1 | 返回列表 |
| 查看: 1035 | 回復(fù): 5 | |||
yalefield金蟲 (文壇精英)
老漢一枚
|
[交流]
【轉(zhuǎn)帖】指針是通往地獄的捷徑 已有5人參與
|
|
作者:fera http://blog.chinaunix.net/space. ... log&cuid=376700 指針指向哪里?……毫無疑問,地獄。 半年前的某個(gè)星期,為了修改一個(gè)bug,我花了整整兩天時(shí)間。 這是一個(gè)指針的錯(cuò)誤,在傳遞參數(shù)的時(shí)候,應(yīng)該傳遞一個(gè)指針而傳遞的是一個(gè)對(duì)象。因?yàn)槌绦蛄鞒桃话銏?zhí)行不到這里,這個(gè)bug一直隱藏在水下。直到我有一天,不小心讓程序執(zhí)行了這段,結(jié)果程序崩潰了(當(dāng)時(shí)我用root用戶執(zhí)行的,真幸運(yùn)沒有損壞系統(tǒng))。有錯(cuò)誤的這段代碼是一位有8年編程經(jīng)驗(yàn)的同事寫的,指針的“邪惡”,可見一斑。 指針就好象一根繩子,繩子那邊是什么被擋住了,我們看不見。你永遠(yuǎn)不知道那邊是一頭牛,還是一顆手榴彈。 指針是什么?你可以把它理解成拴著東西的繩子,也可以說是某個(gè)物體的柄(handle),隨便什么,只要有助于你的理解。你的理解是對(duì)的,可惜只是一部分。 它實(shí)際上是一個(gè)無符號(hào)數(shù),一個(gè)內(nèi)存單元的編號(hào);一般是unsigned long,在32bit CPU上,它是32位的,64位cpu上是64位的。在匯編語言里面,direct addressing、direct addressing采用的都是這個(gè)東西,只不過在C/C++中被封裝成了指針。 現(xiàn)在我們知道了指針的本質(zhì),那么,可以通過成員來獲得對(duì)象的首地址: #define ContainerOf(pointerToField, fieldName, ClassType) \ (ClassType *)((ulong)(pointerToField) - (ulong)((ClassType *)0->fieldName)) 也可以寫出以下語句(為了隱藏某些信息,這樣用戶只知道返回的是一個(gè)句柄handle): typedef unsigned long ulong; typedef ulong SOME_HANDLE; SOME_HANDLE GetObjs() { A* p = new A[10](); return (SOME_HANDLE)p; } 嗯,看起來不錯(cuò),指針的功能很強(qiáng)大。代碼很優(yōu)雅,……看似很好…… 問題是,對(duì)第二段代碼,調(diào)用“h = GetObjs();”的用戶執(zhí)行了這樣的操作:++h;他的本意是將指針移動(dòng)到下一個(gè)元素,可他得到的是什么?假設(shè)GetObjs返回的是 0x00000001, ++h結(jié)果將是0x00000002,而不是期待中的0x00000001 + sizeof(A)。用戶把它當(dāng)成了下一個(gè)A類對(duì)象,進(jìn)行了一些操作,于是,悲劇發(fā)生了……用戶在內(nèi)存中的數(shù)據(jù)全部錯(cuò)亂了,你的系統(tǒng)崩潰了。 是的,指針指向的只是一塊內(nèi)存,但是,這塊內(nèi)存合法嗎?大小是多少?屬于哪種類型?都是未知的。你會(huì)說,如果不知道這塊內(nèi)存屬于哪個(gè)類型,指針?biāo)阈g(shù)就不會(huì)正確。你錯(cuò)了。指針的算術(shù)在編譯時(shí)就知道了該怎么處理,運(yùn)行時(shí)是沒有類型信息的。就是將指針移動(dòng)n * sizeof(A),而sizeof(A)編譯時(shí)就確定了。 再考慮這段代碼,把一組對(duì)象從一個(gè)數(shù)組拷貝到另一個(gè): A ObjCopy(A * const dest, const A * const src, const int nItems) { assert(dest); assert(src); assert(nItems >= 0); while ( nItem-- ) *dest++ = *src++; return dest; } 忽略src里元素不足nItems個(gè)及dest沒有nItems個(gè)空間的因素,這個(gè)函數(shù)依然是錯(cuò)誤的。因?yàn),如果dest - src < nItems的話,從第(dest - src)開始,src中的數(shù)據(jù)將被自己首部的數(shù)據(jù)給覆蓋了。很不幸,你的數(shù)據(jù)又錯(cuò)了,系統(tǒng)可能又要崩潰了……至少,你會(huì)得到錯(cuò)誤的結(jié)果。 好了,這僅僅是一級(jí)指針。換成二級(jí)指針呢? 正因?yàn)橹羔樖浅绦虻腻e(cuò)誤之源,java把對(duì)內(nèi)存的操作封裝起來,不對(duì)外提供指針,這樣就避免了剛才的那些問題。C/C++的忠實(shí)粉絲不要誤以為我在鼓吹java,我本人對(duì)于C/C++是特別鐘愛的,因?yàn)樗鼈兊撵`活性。相信大多數(shù)程序員喜歡它們也是因?yàn)檫@個(gè)。 寫這篇文章的目的就是為了對(duì)指針的復(fù)雜性做一個(gè)說明,希望大家在使用指針的時(shí)候能夠小心。 拋磚引玉,如果有更精辟的想法,希望您能賞光貼在后面! PS: 看了buxoman評(píng)論,覺得有必要澄清一點(diǎn):對(duì)于一個(gè)指針,存在兩個(gè)對(duì)象,一個(gè)是指針本身,一個(gè)是dereference的對(duì)象。因此在讀我這篇文章時(shí)一定要搞清楚,什么時(shí)候說的是指針,什么時(shí)候說的是dereference的對(duì)象。 Copyleft (C) 2007-2009 raof01. 本文可以用于除商業(yè)外的所有用途。此處“用途”包括(但不限于)拷貝/翻譯(部分或全部),不包括根據(jù)本文描述來產(chǎn)生代碼及思想。若用于非商業(yè),請(qǐng)保留此權(quán)利聲明,并標(biāo)明文章原始地址和作者信息;若要用于商業(yè),請(qǐng)與作者聯(lián)系(raof01@gmail.com),否則作者將使用法律來保證權(quán)利。 |
木蟲 (知名作家)

銀蟲 (小有名氣)
金蟲 (職業(yè)作家)

金蟲 (初入文壇)

銀蟲 (正式寫手)

| 6 | 1/1 | 返回列表 |
| 最具人氣熱帖推薦 [查看全部] | 作者 | 回/看 | 最后發(fā)表 | |
|---|---|---|---|---|
|
[考研] 298求調(diào)劑 +6 | 上岸6666@ 2026-03-20 | 6/300 |
|
|---|---|---|---|---|
|
[考研] 289材料與化工(085600)B區(qū)求調(diào)劑 +3 | 這么名字咋樣 2026-03-22 | 4/200 |
|
|
[考研] 尋找調(diào)劑 +4 | 倔強(qiáng)芒? 2026-03-21 | 4/200 |
|
|
[考研] 一志愿中南大學(xué)化學(xué)學(xué)碩0703總分337求調(diào)劑 +3 | niko- 2026-03-22 | 3/150 |
|
|
[考研]
|
酥酥魚.. 2026-03-21 | 3/150 |
|
|
[考研] 材料學(xué)碩301分求調(diào)劑 +7 | Liyouyumairs 2026-03-21 | 7/350 |
|
|
[考研] 0703化學(xué)調(diào)劑 +4 | 妮妮ninicgb 2026-03-21 | 4/200 |
|
|
[考研] 0703化學(xué)297求調(diào)劑 +3 | Daisy☆ 2026-03-20 | 3/150 |
|
|
[考研] 313求調(diào)劑 +4 | 肆叁貳壹22 2026-03-19 | 4/200 |
|
|
[考研] 0805材料320求調(diào)劑 +3 | 深海物語 2026-03-20 | 3/150 |
|
|
[考研] 307求調(diào)劑 +3 | wyyyqx 2026-03-17 | 3/150 |
|
|
[考研] 一志愿中海洋材料工程專碩330分求調(diào)劑 +8 | 小材化本科 2026-03-18 | 8/400 |
|
|
[考研] 0817 化學(xué)工程 299分求調(diào)劑 有科研經(jīng)歷 有二區(qū)文章 +22 | rare12345 2026-03-18 | 22/1100 |
|
|
[考研] 材料學(xué)求調(diào)劑 +4 | Stella_Yao 2026-03-20 | 4/200 |
|
|
[考研] 求調(diào)劑 +3 | 暗涌afhb 2026-03-16 | 3/150 |
|
|
[考研] 材料工程專碩調(diào)劑 +5 | 204818@lcx 2026-03-17 | 6/300 |
|
|
[考研] 0703化學(xué)調(diào)劑 +3 | 妮妮ninicgb 2026-03-17 | 3/150 |
|
|
[碩博家園] 湖北工業(yè)大學(xué) 生命科學(xué)與健康學(xué)院-課題組招收2026級(jí)食品/生物方向碩士 +3 | 1喜春8 2026-03-17 | 5/250 |
|
|
[考研] 考研調(diào)劑 +3 | 淇ya_~ 2026-03-17 | 5/250 |
|
|
[考研] 333求調(diào)劑 +3 | 文思客 2026-03-16 | 7/350 |
|