24小时热门版块排行榜    

查看: 1020  |  回复: 5

yalefield

金虫 (文坛精英)

老汉一枚

[交流] 【转帖】指针是通往地狱的捷径 已有5人参与

作者:fera
http://blog.chinaunix.net/space. ... log&cuid=376700

指针指向哪里?……毫无疑问,地狱。

半年前的某个星期,为了修改一个bug,我花了整整两天时间。

这是一个指针的错误,在传递参数的时候,应该传递一个指针而传递的是一个对象。因为程序流程一般执行不到这里,这个bug一直隐藏在水下。直到我有一天,不小心让程序执行了这段,结果程序崩溃了(当时我用root用户执行的,真幸运没有损坏系统)。有错误的这段代码是一位有8年编程经验的同事写的,指针的“邪恶”,可见一斑。

指针就好象一根绳子,绳子那边是什么被挡住了,我们看不见。你永远不知道那边是一头牛,还是一颗手榴弹。

指针是什么?你可以把它理解成拴着东西的绳子,也可以说是某个物体的柄(handle),随便什么,只要有助于你的理解。你的理解是对的,可惜只是一部分。

它实际上是一个无符号数,一个内存单元的编号;一般是unsigned long,在32bit CPU上,它是32位的,64位cpu上是64位的。在汇编语言里面,direct addressing、direct addressing采用的都是这个东西,只不过在C/C++中被封装成了指针。

现在我们知道了指针的本质,那么,可以通过成员来获得对象的首地址:
#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;
}

嗯,看起来不错,指针的功能很强大。代码很优雅,……看似很好……

问题是,对第二段代码,调用“h = GetObjs();”的用户执行了这样的操作:++h;他的本意是将指针移动到下一个元素,可他得到的是什么?假设GetObjs返回的是 0x00000001, ++h结果将是0x00000002,而不是期待中的0x00000001 + sizeof(A)。用户把它当成了下一个A类对象,进行了一些操作,于是,悲剧发生了……用户在内存中的数据全部错乱了,你的系统崩溃了。

是的,指针指向的只是一块内存,但是,这块内存合法吗?大小是多少?属于哪种类型?都是未知的。你会说,如果不知道这块内存属于哪个类型,指针算术就不会正确。你错了。指针的算术在编译时就知道了该怎么处理,运行时是没有类型信息的。就是将指针移动n * sizeof(A),而sizeof(A)编译时就确定了。

再考虑这段代码,把一组对象从一个数组拷贝到另一个:
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个空间的因素,这个函数依然是错误的。因为,如果dest - src < nItems的话,从第(dest - src)开始,src中的数据将被自己首部的数据给覆盖了。很不幸,你的数据又错了,系统可能又要崩溃了……至少,你会得到错误的结果。

好了,这仅仅是一级指针。换成二级指针呢?

正因为指针是程序的错误之源,java把对内存的操作封装起来,不对外提供指针,这样就避免了刚才的那些问题。C/C++的忠实粉丝不要误以为我在鼓吹java,我本人对于C/C++是特别钟爱的,因为它们的灵活性。相信大多数程序员喜欢它们也是因为这个。

写这篇文章的目的就是为了对指针的复杂性做一个说明,希望大家在使用指针的时候能够小心。

抛砖引玉,如果有更精辟的想法,希望您能赏光贴在后面!

PS:

看了buxoman评论,觉得有必要澄清一点:对于一个指针,存在两个对象,一个是指针本身,一个是dereference的对象。因此在读我这篇文章时一定要搞清楚,什么时候说的是指针,什么时候说的是dereference的对象。

Copyleft (C) 2007-2009 raof01.
本文可以用于除商业外的所有用途。此处“用途”包括(但不限于)拷贝/翻译(部分或全部),不包括根据本文描述来产生代码及思想。若用于非商业,请保留此权利声明,并标明文章原始地址和作者信息;若要用于商业,请与作者联系(raof01@gmail.com),否则作者将使用法律来保证权利。
回复此楼
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

微尘、梦想

木虫 (知名作家)


小木虫(金币+0.5):给个红包,谢谢回帖交流
在国外的一本教材上看到说,指针是C语言的精髓,也是最难的一点,自我感觉用起来挺方便,但总给人一种不踏实的感觉,对于像我这种初学者,使用指针要千万小心啊!
任风云变幻,我笑对人生!
2楼2011-03-23 16:31:00
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

claudebell

银虫 (小有名气)


小木虫(金币+0.5):给个红包,谢谢回帖交流
指针是C/C++精髓的一部分,用的好,无所不能,用的不好,能也不能。
不过正是因为这一点,C/C++比其他很多高级语言要强大。
要这样想,越是难用的东西,一旦用好了就威力无边。
3楼2011-03-23 19:13:55
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

magic7004

金虫 (职业作家)


小木虫(金币+0.5):给个红包,谢谢回帖交流
对于指针,magic7004只能说是风险越大,收益越大。
流氓不可怕,可怕的是流氓有文化,有文化又BH的流氓无敌~~!
4楼2011-03-24 10:12:03
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

womeikongya

金虫 (初入文坛)


小木虫(金币+0.5):给个红包,谢谢回帖交流
是不是地狱得看用的人!
正人行邪法,邪法亦正!!
每天早上叫醒你的不是闹钟,而是梦想!
5楼2011-03-27 18:08:19
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

luojin7653

银虫 (正式写手)


小木虫(金币+0.5):给个红包,谢谢回帖交流
小心小心再小心的使用..
今晚打老虎
6楼2011-03-28 10:34:03
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 yalefield 的主题更新
普通表情 高级回复 (可上传附件)
最具人气热帖推荐 [查看全部] 作者 回/看 最后发表
[考研] 267一志愿南京工业大学0817化工求调剂 +8 SUICHILD 2026-03-12 8/400 2026-03-18 20:55 by winsuccess
[考研] 一志愿天津大学化学工艺专业(081702)315分求调剂 +10 yangfz 2026-03-17 10/500 2026-03-18 20:14 by walc
[考研] 一志愿985,本科211,0817化学工程与技术319求调剂 +7 Liwangman 2026-03-15 7/350 2026-03-18 20:08 by walc
[考研] 一志愿武理材料305分求调剂 +5 想上岸的鲤鱼 2026-03-18 6/300 2026-03-18 17:53 by 无际的草原
[考研] 0854可跨调剂,一作一项核心论文五项专利,省、国级证书40+数一英一287 +8 小李0854 2026-03-16 8/400 2026-03-18 14:35 by 搏击518
[考研] 一志愿西南交大,求调剂 +4 材化逐梦人 2026-03-18 4/200 2026-03-18 14:22 by 007_lilei
[考研] 收复试调剂生 +4 雨后秋荷 2026-03-18 4/200 2026-03-18 14:16 by elevennnne
[考研] 0703化学调剂 +4 pupcoco 2026-03-17 7/350 2026-03-18 12:14 by djl2006
[考研] 301求调剂 +4 A_JiXing 2026-03-16 4/200 2026-03-17 17:32 by ruiyingmiao
[考研] 085600材料与化工求调剂 +5 绪幸与子 2026-03-17 5/250 2026-03-17 16:40 by laoshidan
[考研] 290求调剂 +3 p asserby. 2026-03-15 4/200 2026-03-17 16:35 by wangkm
[考研] 梁成伟老师课题组欢迎你的加入 +8 一鸭鸭哟 2026-03-14 10/500 2026-03-17 15:07 by 一鸭鸭哟
[考研] 283求调剂 +3 听风就是雨; 2026-03-16 3/150 2026-03-17 07:41 by 热情沙漠
[考研] 中科大材料与化工319求调剂 +3 孟鑫材料 2026-03-14 3/150 2026-03-14 20:10 by ms629
[考研] 265求调剂 +4 威化饼07 2026-03-12 4/200 2026-03-14 17:23 by userper
[考研] 308 085701 四六级已过求调剂 +7 温乔乔乔乔 2026-03-12 14/700 2026-03-14 10:49 by JourneyLucky
[考研] [0860]321分求调剂,ab区皆可 +4 宝贵热 2026-03-13 4/200 2026-03-13 22:01 by 星空星月
[考研] 308求调剂 +3 是Lupa啊 2026-03-12 3/150 2026-03-13 14:30 by 求调剂zz
[考研] 0817化学工程与技术考研312分调剂 +3 T123 tt 2026-03-12 3/150 2026-03-13 10:49 by houyaoxu
[考博] 福州大学杨黄浩课题组招收2026年专业学位博士研究生,2026.03.20截止 +3 Xiangyu_ou 2026-03-12 3/150 2026-03-13 09:36 by duanwu655
信息提示
请填处理意见