原来函数入参类型不匹配gcc也能编译通过啊

背景

前一段时间赶工修一个段错误的BUG,修复后代码不再有段错误,但却会导致板子软件与上位机断链,而且还是概率性的。
经过一周的排查,原来是修BUG时引入一个传参错误,给期待struct *形参的函数传了个struct **的实参,导致踩内存,又因为赶工,没仔细看编译告警,于是坑了自己。

复现过程

复现代码:

#include<stdio.h>

void change_info(int *p)  // 形参期待一级指针
{
    *p = 42;
}

int main() {
    int a = 0;
    int *pa = &a;

    printf("a == %d\n", a);
    change_info(&pa);  // 实参传递二级指针,会导致内存访问越界,即踩内存!
    printf("a == %d\n", a);
    return 0;
}

上面代码gcc编译通过,但有告警,说指针类型不匹配:

isp@ax:~/demo$ gcc test_2nd_ptr2.c
test_2nd_ptr2.c: In function ‘main’:
test_2nd_ptr2.c:13:17: warning: passing argument 1 of ‘change_info’ from incompatible pointer type [-Wincompatible-pointer-types]
     change_info(&pa);
                 ^
test_2nd_ptr2.c:3:6: note: expected ‘int *’ but argument is of type ‘int **’
 void change_info(int *p)
      ^~~~~~~~~~~

如果编译的文件很多,很容易忽略这些告警

上面问题代码的运行效果:

isp@ax:~/demo$ ./a.out
a == 0
a == 0

如何规避

  1. 用g++编译器无此问题,直接报error
isp@ax:~/demo$ g++ test_2nd_ptr2.c
test_2nd_ptr2.c: In function ‘int main()’:
test_2nd_ptr2.c:13:18: error: invalid conversion from ‘long long int’ to ‘int*’ [-fpermissive]
     change_info(l);
                  ^
test_2nd_ptr2.c:3:6: note:   initializing argument 1 of ‘void change_info(int*)’
 void change_info(int *p)
      ^~~~~~~~~~~
test_2nd_ptr2.c:15:20: error: cannot convert ‘int**’ to ‘int*’ for argument ‘1’ to ‘void change_info(int*)’
     change_info(&pa);
                    ^
  1. 给gcc传递-Werror选项也能避免此问题
isp@ax:~/demo$ gcc -Werror test_2nd_ptr2.c
test_2nd_ptr2.c: In function ‘main’:
test_2nd_ptr2.c:13:17: error: passing argument 1 of ‘change_info’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     change_info(&pa);
                 ^
test_2nd_ptr2.c:3:6: note: expected ‘int *’ but argument is of type ‘int **’
 void change_info(int *p)
      ^~~~~~~~~~~
cc1: all warnings being treated as errors
  1. 给指针字段添加p_之类的前缀,便于提醒自己

后记

我试了好几种不兼容的指针类型传递,都能编译通过,可见只要参数size匹配就不会报错。
对于非指针类型的参数,一般情况下size不同,此时会报错,但如果是内置类型,则size不同也不会报错,因为会自动向上取整或截断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值