C 不完整类型:链接器不会警告明显的错误

发布于 2025-01-17 07:36:09 字数 955 浏览 2 评论 0原文

文件 main.c 声明了一个不完整类型 int func() 的函数,然后将其用作 int func(void)

该函数在第二个文件中定义为int func(int, int, int),与声明一致,但与用法不一致

我希望链接器能够捕获这种错误,但是即使使用 gcc 的 -Wall -Wextra -pedantic ,代码编译时也不会出现错误或警告。当使用 gdb 调试它时,func 似乎从堆栈中读取垃圾值。难道真的没有办法捕获这样的错误吗?

代码讨论了

// main.c
int func();

int main() {
    func();
}

// func.c
int func(int a, int b, int c) {
    return a * b * c;
}

我运行的 Shell 命令

$ gcc main.c func.c -Wall -Wextra -pedantic -ggdb
$ gdb -q a.out
Reading symbols from a.out...
(gdb) b 1
Breakpoint 1 at 0x1131: file main.c, line 4.
(gdb) r
Starting program: /tmp/example/a.out 

Breakpoint 1, main () at main.c:4
4               func();
(gdb) s
func (a=1, b=-8376, c=-8360) at func.c:2
2               return a * b * c;

A file main.c declares a function of the incomplete type int func(), then uses it as int func(void).

The function is defined in a second file as int func(int, int, int), which is consistent with the declaration, but not with the usage.

I would expect that kind of error to be caught by the linker, but the code compiles with no errors or warnings, even when using gcc's -Wall -Wextra -pedantic. When debugging it with gdb, func seems to read garbage values from the stack. Is there really no way to catch such an error?

The code discussed

// main.c
int func();

int main() {
    func();
}

// func.c
int func(int a, int b, int c) {
    return a * b * c;
}

Shell commands I ran

$ gcc main.c func.c -Wall -Wextra -pedantic -ggdb
$ gdb -q a.out
Reading symbols from a.out...
(gdb) b 1
Breakpoint 1 at 0x1131: file main.c, line 4.
(gdb) r
Starting program: /tmp/example/a.out 

Breakpoint 1, main () at main.c:4
4               func();
(gdb) s
func (a=1, b=-8376, c=-8360) at func.c:2
2               return a * b * c;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫性小仙女 2025-01-24 07:36:10

C 中没有像 C++ 中那样的函数重载。因此,编译器不会构建包含有关函数参数信息的损坏的函数外部名称。

在使用函数之前,您始终应该提供函数原型。在这种情况下,编译器将能够发现不一致的地方。

C 标准仅保证(6.5.2.2 函数调用)

2 如果表示被调用函数的表达式的类型为
包括原型,参数的数量应与
参数的数量。
每个参数都应具有一个类型,使其
值可以分配给具有不合格版本的对象
其对应参数的类型。

否则

6 如果表示被调用函数的表达式的类型为
不包括原型,整数提升是在
每个参数以及具有 float 类型的参数都会提升为
双倍的。这些称为默认参数促销。 如果
参数数量不等于形参数量,
行为未定义。

There is no function overloading in C as in C++. So the compiler does not build mangled function external names that include information about function parameters.

You always should provide function prototypes before using functions. In this case the compiler will be able to find an inconsistence.

The C Standard only guarantees that (6.5.2.2 Function calls)

2 If the expression that denotes the called function has a type that
includes a prototype, the number of arguments shall agree with the
number of parameters.
Each argument shall have a type such that its
value may be assigned to an object with the unqualified version of the
type of its corresponding parameter.

Otherwise

6 If the expression that denotes the called function has a type that
does not include a prototype, the integer promotions are performed on
each argument, and arguments that have type float are promoted to
double. These are called the default argument promotions. If the
number of arguments does not equal the number of parameters, the
behavior is undefined.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文