奇怪的 gcc 警告和消毒剂崩溃

Weird gcc warning and sanitizer crash

我在我的项目中遇到了一些奇怪的 gcc 警告。让我们在 3 个文件中查看这个简单示例:

struct.h

typedef struct {
    int a;
    long b;
    char *c;
} myStruct;

func.c

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

myStruct* func() {
    myStruct* new = (myStruct*) malloc(sizeof(myStruct));
    new->a = 42;
    new->b = 84;
    new->c = "lol_ok\n";
    return new;
}

void prn(myStruct* x) {
    printf("%d\n", x->a);
}

main.c

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

#include "struct.h"

int main() {
    myStruct* ms = func();
    prn(ms);
    return 0;
}

所以我收到以下警告:

main.c: In function ‘main’:
main.c:8:24: warning: initialization makes pointer from integer without a cast
         myStruct* ms = func();

此外,当我用 -Wall -Wextra 构建它时,我得到更多:

main.c: In function ‘main’:
main.c:8:9: warning: implicit declaration of function ‘func’ [-Wimplicit-function-declaration]
         myStruct* ms = func();
         ^
main.c:8:24: warning: initialization makes pointer from integer without a cast
         myStruct* ms = func();
                        ^
main.c:9:2: warning: implicit declaration of function ‘prn’ [-Wimplicit-function-declaration]
  prn(ms);

这是什么意思?如果使用 -fsanitize=undefined -fsanitize=address 构建,它也会崩溃,这很奇怪。为什么?

缺乏原型。

struct.h 中包含 func() 的原型。

myStruct* func(void);

func() 的原型不可见时,编译器假定(C99 之前)它 returns 是 int。但是 func() 实际上 returns 一个 myStruct*

请注意,此隐式 int 规则已从 C99 删除。所以从技术上讲,您的代码在 C99 和 C11 中的格式不正确。

提高警告级别会有所帮助。 gcc 提供 an option 来捕捉这个:

-Wimplicit-function-declaration
main.c:8:9: warning: implicit declaration of function ‘func’ [-Wimplicit-function-declaration]

这意味着 main.c 不知道函数 func 是什么样子。那是因为在func.c里定义了,但是main.c看不到func.c.

里有什么

您需要做的是在 struct.h 中声明 func(),如下所示:

myStruct* func( void ); 

一旦有了它,main.c 就知道函数 func 是什么了。

.....

另外,你得到 "initialization makes pointer from integer without a cast" 的原因是因为没有看到函数的声明,编译器假定它 returns int.