【问题标题】:Weird gcc warning and sanitizer crash奇怪的 gcc 警告和消毒剂崩溃
【发布时间】:2015-12-08 20:30:47
【问题描述】:

我在我的项目中遇到了一些奇怪的 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 构建,它也会崩溃,这很奇怪。为什么?

【问题讨论】:

    标签: c gcc compiler-warnings


    【解决方案1】:

    缺乏原型。

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

    myStruct* func(void);
    

    当func() 没有可见的原型时,编译器假定(C99 之前)它返回一个int。但func() 实际上返回一个myStruct*。

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

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

    -Wimplicit-function-declaration
    

    【讨论】:

      【解决方案2】:
      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 是什么。

      ....

      此外,您得到“初始化使指针从整数而不进行强制转换”的原因是因为没有看到函数的声明,编译器假定它返回 int。

      【讨论】:

      • @FiddlingBits 否。只有在未找到函数定义时才会发生链接器错误(未定义对 blah 的引用)。但是在这里,定义确实存在并且可用。否则,gcc 将失败,而不是发出警告并默认 int。
      猜你喜欢
      • 2016-07-28
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多