现在,当我用C中的指针犯了一个编程错误时,我遇到了一个很好的分段错误,程序崩溃了,调试器甚至可以告诉我哪里出错了。
在没有内存保护的情况下,他们是如何做到的?我可以看到一个DOS程序员在弄错时摆弄着他,并使整个操作系统崩溃。虚拟化不可用,因此他所能做的就是重新启动并重试。真的那样吗?
现在,当我用C中的指针犯了一个编程错误时,我遇到了一个很好的分段错误,程序崩溃了,调试器甚至可以告诉我哪里出错了。
在没有内存保护的情况下,他们是如何做到的?我可以看到一个DOS程序员在弄错时摆弄着他,并使整个操作系统崩溃。虚拟化不可用,因此他所能做的就是重新启动并重试。真的那样吗?
Answers:
我可以看到一个DOS程序员在弄错时摆弄着他,并使整个操作系统崩溃。
是的,那几乎就是发生了什么。在大多数具有内存映射的系统上,位置0被标记为无效,因此可以很容易地检测到空指针,因为这是最常见的情况。但是还有很多其他情况,它们造成了严重破坏。
冒着听起来像个盖茨的危险,我应该指出,当前对调试的关注不是过去。以前需要付出更多的努力来编写正确的程序,而不是消除错误程序中的错误。其中一些是因为这是我们的目标,但很多是因为这些工具使工作变得困难。尝试在纸上或打孔卡上编写程序,而不是在IDE中,并且没有交互式调试器的好处。它给您带来正确感。
早在我的时代,我们就没有内存保护功能,也没有那么出色的业务!我们使用printf来确定我们在程序中的位置,并且我们喜欢它!
尽管非常认真,但这通常意味着我们要更加小心。在调用malloc的地方,程序中的其他地方必须有空闲空间,并且这种检查非常严格,因为正如您已经清楚指出的那样,在出现问题的情况下,分段错误不是有用的错误。
对于此类错误,您最好的办法是尝试了解何时发生此类分段错误(使用printf),然后查看代码,确定为何此时对内存的访问无效并从那里进行反向操作。
从本质上讲,今天发生了同样的事情,除了我们使用调试器确定何时发生错误外,但您仍然必须了解发生错误的原因,而且这并不总是比发现错误发生的行那么简单。错误会导致诸如连锁反应之类的错误,如果您那时是C程序员,那么您将花费20%的时间进行编码,而其余时间则花费大量时间来修复错误。
好 ..
分段故障确实是一个很好的指示,表明出了点问题,但您仍然必须找到根本原因。因此,如果您问的问题是如何找到根本原因,那么答案与今天相比并没有太大不同。当然,语言和工具变得更易于使用,但是一般的taktik是相同的:
在更抽象的级别上,您可以使用三种方法:1.使用代码2.在程序运行时查看程序3.在执行愚蠢的操作后查看结果
顺便说一句,指针错误不必创建段错误。
作为Amiga程序员,我几乎全部使用了它。是的,在常见实践中会重新开始。
有一次,我在当时著名的Windows 3.1 Presentation软件上进行错误修复。
我有一个错误,当它发生时,导致了死亡蓝屏。
该错误仅在某个循环已执行1000次以上时发生。我使用调试器的高级功能使断点通过1000次,然后我仔细地逐步执行了该程序。每次我走得太远或跳过包含Windows Blue Screened错误的函数调用时。
最终,经过几天的工作,我将其范围缩小到内存不足的功能,并且不显示错误消息,而是将错误消息附加到缓冲区。在随后的每次迭代中,它浪费了更多的内存,直到关键内容被覆盖并且Windows被浪费为止。
调试技巧和毅力是解决方案。