【问题标题】:Best practices to avoid problems with pointers [duplicate]避免指针问题的最佳实践[重复]
【发布时间】:2010-11-28 19:28:39
【问题描述】:

与指针有关的程序员错误的实际结果是什么?

当程序员创建指针错误时会发生什么“不良影响”?

最好有代码的实际例子。

【问题讨论】:

  • Brian、Charles Bailey、tanascius、starblue、Xetius 中的任何人能否告诉我这个问题与编程无关?
  • 根据FAQ,问题应该是“详细而具体的”。这是一个非常笼统的问题,询问“战争故事”表明您正在邀请“扩展讨论”。 Wiki 与否,这超出了 SO 邀请的问题类型的范围。
  • 对不起,这仍然不是一个真正的问题 - 这是一个书本长度的讨论主题
  • @George Stocker-就个人而言,我真的将其解释为要求最佳实践以及他为什么应该使用它们......不一定要求“有一次我......”......至少这是我的解释。
  • 就个人而言,我投票决定关闭,因为它太通用了。我实际上并没有注意到它是否是社区 wiki。

标签: c pointers


【解决方案1】:

指针被滥用时可能出错的地方:

  1. 内存泄漏 - 您在方法中分配一个指针,然后让它超出范围而没有正确释放它。指向堆上内存的指针现在丢失了,但内存仍然分配。现在释放这个内存是非常困难的。 More info from Wikipedia.

  2. 访问冲突 - 您创建一个指向您无权访问或不存在的内存地址的指针。毕竟指针只是整数,并且可以像任何其他数字一样进行操作。当您尝试取消引用无效指针时,您的程序将停止。 More info from Wikipedia.

  3. 空指针错误 - 这是访问冲突的一种特殊情况。 “停放”指针以使其不特别指向任何东西的正确方法是将其值设置为零或空。尝试取消引用空指针将停止您的程序。 More info from Wikipedia.

  4. 缓冲区溢出 - 您为 30 个字符的字符缓冲区分配指针。然后,您继续将用户输入(来自套接字、文件、控制台等)流式传输到此缓冲区中。如果您未能正确实施缓冲区边界检查,那么您的程序可能会在缓冲区中放入超过 30 个字符。这将损坏存储在内存中缓冲区附近的任何数据,并可能使您面临恶意代码攻击。 More info from Wikipedia.

  5. 内存损坏 - 指针只是一个整数,其中包含它所指向的东西的内存地址。作为一个整数,pointer arithmetic 可用于以各种有趣的方式操作指针的值。如果指针计算出错,可能会出现细微的错误。指针现在将指向内存中的某个未知位置,当它被取消引用时,任何事情都可能发生。

  6. 空终止字符串问题 - 当需要空终止字符串的字符串库函数被提供非空终止的字符指针时,就会出现这些错误。字符串库函数将继续处理字符,一次一个,直到找到一个空值——无论它在哪里。 A joke best illustrates this bug.

【讨论】:

  • 如果你不介意,你能举一些例子(如果有的话)来改进你的答案吗?
【解决方案2】:

来自http://xkcd.com

我想我是按字面意思理解插图要求

【讨论】:

  • @unwind -- 感谢您添加工具提示。
  • 这是对问题的真正答案吗? (无论如何它仍然是一部好漫画)
  • @Ravi - 是的。 New Shimmer:它是一种甜点浇头和地板蜡。 :-)
【解决方案3】:

这一切都归结为访问未指定的内存区域。在分配区域外读/写,取消引用未初始化的指针。基本上就是这样。

也存在对指向对象类型的误解,但这通常需要付出一些努力才能避免被编译器大喊大叫。

还有内存泄漏,但那是另一回事,它与分配有关,而不是指针本身。

【讨论】:

    【解决方案4】:

    只需初始化您的指针变量和良好的清理将消除 99% 的问题。通过良好的清理,我的意思是;释放内存并将指针变量设置为 null。

    否则,您需要清晰的设计来传递指针以及负责清理内存的代码。如果您最终处于不知道哪些代码将最后使用内存并且应该清理的情况下,那么您有一种设计气味,您需要修复它以维护您的理智。

    【讨论】:

    • 或者更好的是,一开始就不要使用指针。
    【解决方案5】:
    • 永远不要忽视任何警告。
    • Splint一样使用static analysis tools

    • 最重要的是:使用dynamical analysis tools - 他们经常提醒错误使用指针、打破数组边界等'我确保这些错误为零,即使程序似乎正在运行......

    【讨论】:

      【解决方案6】:

      取消引用坏指针时的结果是未定义的,因此根据定义,当您弄乱指针时可能会发生任何事情。这就是为什么您应该尽可能避免使用它们。

      C-ish 语言是围绕指针的使用而设计的,它们现在占主导地位,所以这对某些人来说听起来像是疯狂的建议。我建议人们研究旨在最大限度减少指针使用并检查常见错误的语言,例如 Ada。

      我最喜欢的指针轶事如下:我曾经在佛罗里达州的一个小组工作,该小组在新墨西哥州的库尔特兰空军基地(大部分在大陆的另一边)维护 3 架直升机的网络飞行模拟。有一天突然出现了一个崩溃错误。当地的现场技术无法修复它,所以大约一个月后,我们的一位工程师飞过来查看它。两周后,他感到困惑,所以另一个人被拉了进来。又过了一个月,我们的顶级工程师也飞过来帮忙。

      又过了一个月(一直以来,公司支付 3 个人住在酒店的费用,租车,每两个周末飞回来),他们找到了问题所在。事实证明,有人在数组末尾索引一个(C 也没有索引检查)。然后他们抓住那个位置的废话,通过网络将它传递给第二台机器,它使用该值作为数组索引。由于该代码也在 C 中,因此再次没有检查。它抓住了那个位置的垃圾并将其发送到第三台机器。那台机器使用废话作为指针并试图取消引用它。 繁荣

      因此,一台机器上的代码中的错误导致两台机器从网络中删除。数以千计的美元和几个月的宝贵时间都浪费在了追踪它上。这都是因为他们使用了一种没有范围检查的语言。

      【讨论】:

        【解决方案7】:

        原始指针是邪恶的。无法知道它们是否有效(悬空指针),它们是否已被初始化(如果在初始化时未设置为 NULL,它们可能看起来实际上指向某个东西),并且不清楚谁有责任释放资源它们指向(例如调用者检索或返回指针的函数)。

        如果没有智能指针,我一天都活不下去。 std::auto_ptr 当我转移所有权时(明确责任), boost::shared_ptr 当所有权被共享时, boost::weak_ptr 当有人“观察”资源时。

        【讨论】:

          【解决方案8】:

          我不知道您是否仍然可以这样做,但我记得几年前我们会编写一个脚本,通过清除整个 RAM 来使系统崩溃。这是我们的做法。

          int *i;
          
          while(1){
             *i = 0;
             i++;
          }
          

          至少我记得我们是这样做的。我相信它现在不会起作用。

          【讨论】:

          • 我当然不敢尝试。(至少在我的电脑上)
          • 应用程序最终会崩溃,但操作系统不允许应用程序在其内存区域之外进行写入。因此系统不应该崩溃。
          • 说说指针问题,你忘记初始化了。
          • 嘿..那是内存不足...几年没用指针了。
          • 在具有内存保护的现代操作系统(即所有当前主流操作系统)上,这只会因内存访问错误/分段错误而崩溃。 MMU 和内存保护存在的真正原因是为了防止程序做这样的事情:-)。
          【解决方案9】:

          最好的做法是尽可能避免使用指针。对大部分软件使用托管语言,而对于访问系统资源或效率所必需的小部分,只使用 C。换句话说,C 应该被视为与汇编语言大致相同。

          (我帮助关闭的原始问题“不是一个真正的问题”完全不同,而且过于宽泛而无用。)

          【讨论】:

          • 避免使用指针??这根本不是一个好的解决方案。
          • 您可以通过使用 Assembly! 来避免使用指针!大声笑一个愚蠢的评论
          • 不,汇编比C还要差,C可以被认为是(大部分)机器无关的汇编语言。
          猜你喜欢
          • 2019-04-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-11
          • 2012-02-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多