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

銀蟲 (小有名氣)

金蟲 (初入文壇)

銀蟲 (正式寫手)

| 6 | 1/1 | 返回列表 |
| 最具人氣熱帖推薦 [查看全部] | 作者 | 回/看 | 最后發(fā)表 | |
|---|---|---|---|---|
|
[考研] 306求調劑 +4 | 來好運來來來 2026-03-22 | 4/200 |
|
|---|---|---|---|---|
|
[考研] 0703化學297求調劑 +3 | Daisy☆ 2026-03-20 | 3/150 |
|
|
[基金申請]
學校已經(jīng)提交到NSFC,還能修改嗎?
40+4
|
babangida 2026-03-19 | 9/450 |
|
|
[考研] 268求調劑 +9 | 簡單點0 2026-03-17 | 9/450 |
|
|
[考研] 330求調劑0854 +3 | assdll 2026-03-21 | 3/150 |
|
|
[考研] 332求調劑 +3 | 鳳凰院丁真 2026-03-20 | 3/150 |
|
|
[考研] 306求調劑 +4 | chuanzhu川燭 2026-03-18 | 4/200 |
|
|
[考研] 310求調劑 +3 | baibai1314 2026-03-16 | 3/150 |
|
|
[考研] 機械專碩299求調劑至材料 +3 | kkcoco25 2026-03-16 | 4/200 |
|
|
[考研] 化學求調劑 +4 | 臨澤境llllll 2026-03-17 | 5/250 |
|
|
[考研] 一志愿西南交大,求調劑 +5 | 材化逐夢人 2026-03-18 | 5/250 |
|
|
[考研] 324求調劑 +5 | lucky呀呀呀鴨 2026-03-20 | 5/250 |
|
|
[考研] 085600材料與化工 +8 | 安全上岸! 2026-03-16 | 8/400 |
|
|
[考研] 一志愿華中農(nóng)業(yè)071010,總分320求調劑 +3 | 困困困困坤坤 2026-03-20 | 3/150 |
|
|
[考研] 求調劑 +3 | eation27 2026-03-20 | 3/150 |
|
|
[考研] 085410人工智能專碩317求調劑(0854都可以) +4 | xbxudjdn 2026-03-18 | 4/200 |
|
|
[考研] 【同濟軟件】軟件(085405)考研求調劑 +3 | 2026eternal 2026-03-18 | 3/150 |
|
|
[考研] 326求調劑 +5 | 上岸的小葡 2026-03-15 | 6/300 |
|
|
[考博] 26申博 +4 | 八6八68 2026-03-16 | 4/200 |
|
|
[論文投稿] 有沒有大佬發(fā)小論文能帶我個二作 +3 | 增銳漏人 2026-03-17 | 4/200 |
|