C 程序在指针运算后崩溃(仅在某些计算机中)

Posted

技术标签:

【中文标题】C 程序在指针运算后崩溃(仅在某些计算机中)【英文标题】:C program crashes after pointer arithmetic (only in some computers) 【发布时间】:2018-07-27 09:31:43 【问题描述】:

我有以下代码(不是我写的,简化后只显示有问题的部分):

#include <stdlib.h>

typedef struct test_struct 
    unsigned int foo;
    char *dummy;
 test_struct;

int main()

    test_struct *s = (test_struct *) malloc(10 * sizeof(test_struct));
    s = (test_struct *)((unsigned long)s + 16);
    s->foo = 1; // crash!

程序为 10 个结构(在我的平台中为 10*24 字节)分配内存。然后,指针增加了 16 个字节,并尝试在该位置写入一个数字。

我已经在 4 台计算机上测试了这个 sn-p。其中两个在 Windows 7 x64 上运行,并且运行良好。另一个在 lubuntu x64 上运行,也可以按预期工作。另一个是 Windows 10 x64,它崩溃了。

你能帮我理解这些行有什么问题吗?我正在使用执行此操作的第三方库,但我不知道到底发生了什么。

【问题讨论】:

你知道一个结构是24字节吗?即使是这样,那你为什么认为指向内存的 16 字节指针是有效的呢?添加 24 字节的偏移量(或任何 sizeof(test_struct) 可能)不会更有意义吗? 导致这个问题的真正问题是什么?你为什么要问?这样的用例是什么? “按预期工作”这句话有点棘手。我认为这只是意味着您没有看到崩溃。仅仅因为程序“按预期工作”并不意味着它不是错误。你可以运行它,不会出错,但它仍然可能正在写入它不应该写入的内存。 @Someprogrammerdude,我知道 struct if 24 bytes 因为我在测试中打印了值。我希望指针是有效的,因为我分配了足够的空间(即使我分配了 5000 个字节它也不起作用)。我同意这没有多大意义,但我没有编写代码,我正在尝试修复它。谢谢! 问题不仅在于尺寸,还在于对齐。有些数据不能放在某些系统上的任何地址上。在这些平台上,未对齐的访问可能会导致异常。 【参考方案1】:

s = (test_struct *)((unsigned long)s + 16);

在某些平台上long 不足以存储指针,因此请改用uintptr_t

s = (test_struct *)((uintptr_t)s + 16);

程序为 10 个结构(在我的例子中为 10*24 字节)分配内存。然后,指针增加了 16 个字节

无论您要实现什么,请注意结构的大小也取决于平台。不仅结构内部的字段,不同平台上的填充也可能不同。

所以在计算中我们最好使用sizeofoffsetof 而不是像16 这样的幻数。

【讨论】:

值得注意的是,使用 Visual C++ 编译器的 64 位 Windows 就是这些平台之一。 谢谢,安德烈。我说“在我的情况下”是 10*24 字节,因为我打印了 sizeof(struct) 结果来检查该结构占用了多少内存。此外,真正的库不会添加 16 字节的硬编码值,但我发现在给定的执行或给定的设置中,当它崩溃时它是 16 字节。我不明白的是,如果分配了很多内存,为什么即使不是分配部分的初始位置也不能写入数字?我不喜欢这个库的编码方式,但我必须修复它才能运行我的程序。 @ZuhaitzBeloki 您无法写入,因为您正在转换为 unsingned long,在某些平台上可能只有 32 位。您应该改用uintptr_t。请参阅我的答案的开头;) 你是对的,@AndriyBerestovskyy。现在可以了。谢谢!【参考方案2】:

test_struct *s = (test_struct *) malloc(10 * sizeof(test_struct)); s = (test_struct *)((unsigned long)s + 16);

您的程序中存在多个错误:- 1.您应该了解内存分配完全取决于操作系统。如何以及为什么要长时间递增 16,它可能会溢出。 2.在 s 中更改地址存储后,您正在访问现在无效的 foo。 3.使用valgrind并检查是否无效。

【讨论】:

以上是关于C 程序在指针运算后崩溃(仅在某些计算机中)的主要内容,如果未能解决你的问题,请参考以下文章

MFC 程序仅在某些 Windows 7 32 位计算机上存在运行时错误 R6025,并在其上安装 Visual Studio 后修复

C指针及其运算

C指针及其运算

Heisenbug:WinApi 程序在某些计算机上崩溃

访问 ccomptr 指针和应用程序崩溃时访问冲突(c 系统异常代码:c0000005)

大牛带你学 | C语言的指针及相关运算符总体归纳