【问题标题】:Pointer Dereferencing = Program Crash指针取消引用 = 程序崩溃
【发布时间】:2009-10-16 18:30:05
【问题描述】:
unsigned int *pMessageLength, MessageLength;
char *pszParsePos;

...
//DATA into pszParsePos
...

printf("\nMessage Length\nb1: %d\nb2: %d\nb3: %d\nb4: %d\n",
    pszParsePos[1],pszParsePos[2],pszParsePos[3],pszParsePos[4]);

pMessageLength= (unsigned int *)&pszParsePos[1];

MessageLength = *((unsigned int *)&pszParsePos[1]);

//Program Dies

输出:

消息长度 b1: 0 b2: 0 b3: 0 b4: 1

我不明白为什么这会导致我的程序崩溃。有人可以解释一下,或者至少建议一种不会崩溃的替代方法吗?

感谢您的宝贵时间!

【问题讨论】:

  • 你没有提到:什么操作系统,什么微处理器,当它“死”时你看到了什么错误?
  • 它在嵌入式 Blackfin 处理器上的 uClinux 中运行 ansi C。当它“死”时会显示“总线错误”,但我认为这与 Blackfin 外设之一没有正确停止有关(但我肯定是错的)。
  • 您的系统可能无法访问未对齐的指针。
  • 只需在编辑器窗口中突出显示代码,然后单击看起来像 101010 的小按钮。
  • 是的,我现在弄清楚了代码格式。谢谢。

标签: c pointers


【解决方案1】:

总线错误意味着您尝试访问对齐不正确的数据。具体来说,处理器似乎要求int 比任何地方都更严格地对齐,如果您的*pszParsePos 对齐,比如说在int 边界上(这取决于您如何初始化它,但会发生,例如,如果你使用malloc),那么&pszParsePos[1]肯定不是。

解决此问题的一种方法是显式构造MessageLength,即类似

MessageLength = (pszParsePos[1] << 24) | (pszParsePos[2] << 16) | (pszParsePos[3] << 8) | pszParsePos[4]

(或者如果它应该是 little-endian,则相反)。如果您真的想打双关,请确保您访问的指针正确对齐。

【讨论】:

  • 这正是正在发生的事情。感谢您的帮助!
【解决方案2】:

以下是我认为出错的地方:

您在评论中添加了您在 Blackfin 处理器上运行的信息。我在一些网站上查找了这一点,他们声称 Blackfin 需要所谓的 aligned 访问。也就是说,如果您正在向/从内存读取或写入 32 位值,则物理地址必须是 4 字节的偶数倍。

C 中的数组从 [0] 开始索引,而不是 [1]。一个 4 字节的 char 数组以元素 [3] 结尾。

在您的代码中,您有一个 4 字节的 char 数组:

  • 您将其视为从索引 1 开始。
  • 您可以通过指针强制转换通过 32 位内存获取转换为 DWORD。

我怀疑您的 4 字符数组与 4 字节边界对齐,但是当您在 +1 字节位置开始内存访问时,您会遇到数据总线错误对齐错误。

【讨论】:

  • 不,字符数组比 4 个字节长得多,我想要的数据位于索引 [1] 到 [4] 中。我明白你的意思,这很有帮助。