使用未定义的指针分配内存

时间:2014-04-24 20:02:55

标签: c

gcc -Wall在没有警告的情况下编译时,我感到很惊讶。这真的是合法的C吗?编写这样的代码有什么风险?

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int a;
  int b;
} MyStruct;

int main(void) {
  MyStruct *s = malloc(sizeof(*s)); // as opposed to malloc(sizeof(MyStruct))
  s->a = 5;
  printf("%d\n", s->a);
}

3 个答案:

答案 0 :(得分:5)

它不仅合法,而且更可取。这样您就可以让编译器推导出实际类型而不是手动执行它。

答案 1 :(得分:2)

sizeof在编译时进行评估。在此上下文中,*s解析为*s的类型,它不会取消引用指针。

这是使用sizeof的规范方式。如果您使用sizeof(int),那么如果类型发生更改(在这种情况下,可能不太可能,但仍然如此),则会留下错误的开头。

答案 2 :(得分:1)

书写

MyStruct *s = malloc(sizeof(*s));

具有完全相同的效果
MyStruct *s = malloc(sizeof(MyStruct));

除了现在你只编写MyStruct 一次。也就是说,您分配的对象会自动确定其源类型,从而减少出错的可能性。

例如 - 它发生在我身上 - 你从MyStruct开始。然后,您决定为不同目的另外MyStruct。因此,您最终会得到两种不同的结构:MyStructAnotherStruct

然后,您重构代码并将一些变量从MyStruct更改为AnotherStruct,最后以

结尾
AnotherStruct *s = malloc(sizeof(MyStruct));

实际上可能在几种情况下,或者很长一段时间内,直到你再做一点,并且在那时,在任一结构中完全无关的改变。在 点,您的代码将变为kaboom。

E.g。

typedef struct {
        int a;
        int b;
} StructA;

typedef struct {
        int a;
        int b;
        int c;
} StructB;

int main() {
        // No problem here except wasted space
        StructA *s = malloc(sizeof(StructB));

        // t->c dwells in undefined country
        StructB *t = malloc(sizeof(StructA));
}