3

昨晚我花了很尴尬的时间来追踪我的应用程序中的段错误。最终,事实证明我写的是:

ANNE_SPRITE_FRAME *desiredFrame;
*desiredFrame = anne_sprite_copy_frame(&sprite->current);

代替:

ANNE_SPRITE_FRAME desiredFrame;
desiredFrame = anne_sprite_copy_frame(&sprite->current);

在第 1 行中,我创建了一个类型化指针,在第 2 行中,我将取消引用的指针的值设置为由anne_sprite_copy_frame().

为什么这是个问题?为什么编译器完全接受这个?我能想到的是,示例 1 中的问题是:

  1. 我为指针保留空间,但不是它指向的内容,或者
  2. (不太可能)它试图将返回值存储在指针本身的内存中
4

4 回答 4

5

在第 1 行中,我创建了一个类型化指针,在第 2 行中,我将取消引用的指针的值设置为由 anne_sprite_copy_frame() 返回的结构。

这两个在 C 中都是允许的,这就是编译器完全可以接受的原因。

编译器不会检查以确保您的指针实际上指向任何有意义的东西 - 它只是取消引用和分配。

C 语言最好和最差的特性之一是编译器几乎不会为你做健全性检查——它遵循你的指令,并且完全按照你的指示去做。你告诉它做两个合法的操作——即使变量没有正确初始化。因此,您会遇到运行时问题,而不是编译时问题。

于 2013-08-19T17:46:09.967 回答
3

我为指针保留空间,但不是它指向的内容

是的,正是。但是编译器(除非它进行一些静态分析)无法推断出这一点。它只看到语法有效并且类型匹配,所以它编译你的程序。但是,取消引用未初始化的指针是未定义的行为,因此您的程序很可能会错误地工作。

于 2013-08-19T17:46:07.267 回答
3

指针未初始化,但它仍然有一个值,所以它指向某个地方。将返回值写入该内存地址会覆盖那里发生的任何事情,从而调用未定义的行为。

从技术上讲,编译器不会告诉您语法上有效的构造会导致未定义(甚至可能是意外)的行为,但是如果没有针对此特定用法发出警告,我会感到惊讶。

于 2013-08-19T17:46:34.217 回答
1

C 是弱类型的。您可以将任何东西分配给任何具有明显后果的东西。如果您不想花费数夜时间发现“愚蠢”的错误,则必须非常小心和自律。我的意思是没有冒犯。由于数组绑定溢出覆盖了其他变量并且只出现在尝试使用这些变量的代码的其他部分中,我遇到了同样的问题。恶梦!这就是为什么 Java 更容易处理的原因。使用 C,你是一个没有网的杂技演员,使用 Java,你可以承受跌倒。也就是说,我并不是说 Java 更好。C 有其存在的理由。

于 2013-08-19T17:53:58.620 回答