我最近遇到了一些使用"酷破解"的代码,如下所示:
#include <stddef.h>
#include <stdlib.h>
struct foo {
int a;
char *b;
int optional;
char huge[5000];
/* lots more members */
};
void myfunc(void) {
struct foo *p;
p = malloc(offsetof(struct foo, optional));
if (p) {
p->a = 17;
p->b = "Hello";
/* do stuff with p->a and p->b */
free(p);
}
}
这个想法是通过只分配struct foo
中实际要使用的部分来"节省内存"。
我看到了这个代码之所以是个坏主意的许多明显原因:如果重新排序struct foo
的成员,或者忘记允许使用哪些成员,或者意外地将*p
赋值或按值传递给函数,它肯定会崩溃。(在链接的代码中,对于大多数程序只会调用几次的函数,每次调用可以节省80个字节。(
但就C标准而言,它实际上是未定义的行为还是非法的?如果是这样的话,是否有现实生活中的实现无法按预期工作的例子?
我认为标准没有考虑这种模式。在编写标准时,它肯定是常用的,并得到了所有常见实现的支持。虽然没有明显的理由表明任何通用实现都不支持它,但我不知道《标准》的作者是否想排除客户不需要这种模式的实现的可能性,如果他们注意到分配给指向结构类型的指针的地址对他们来说太大了,他们会尖叫。相反,我认为他们希望实现在没有充分理由的情况下有效地处理这些构造,但不想推测什么是"充分理由">
至于这样的代码是否可靠工作的问题,没有什么特别的理由不应该这样做,我也不知道在任何特定情况下它会导致clang或gcc出现问题,但当前或未来的版本可能会发现一些"聪明"的优化,在这些优化失败的地方。