gcc对void型指针的类型检查有问题?
创始人
2024-04-06 15:26:37

背景

前一段时间遇到一个问题,我调用了一个隔壁部门的库,这个库在调用前要创建context,程序退出前要销毁context,问题是销毁的时候,出现段错误了。
经过一番定位,发现是库的销毁接口跟库的常规处理接口稍有差别

typedef void *xxx_handle;
//常规接口
int xxx_proc(xxx_handle h, int arg);
//创建接口
xxx_handle xxx_create();
//销毁接口
int xxx_destroy(xxx_handle *ph);

销毁接口的第一个入参类型不是void*,而是void **
等等,为什么编译没有告警指针类型不匹配?

gcc对void *的检查

下面这行代码不会有任何告警,但指针类型其实是不匹配的:

#includetypedef void *handle;void f(handle *ph) {
}int main() {handle h = NULL;f(h);return 0;
}

这说明,gcc不会告警一级void指针和二级void指针的类型不匹配!

尝试用g++编译问题代码,直接报error:

test_void_ptr.c: In function ‘int main()’:
test_void_ptr.c:10:8: error: invalid conversion from ‘handle {aka void*}’ to ‘void**’ [-fpermissive]f(h);^
test_void_ptr.c:5:6: note:   initializing argument 1 of ‘void f(void**)’void f(handle *ph) {^

看样子是C语言编译器特有的现象,C还是太permissive了。

尝试规避

但是你如果把void关键字替换成int,其他不做修改,则gcc立马报incompatible pointer type告警:

test_void_ptr.c: In function ‘main’:
test_void_ptr.c:10:7: warning: passing argument 1 of ‘f’ from incompatible pointer type [-Wincompatible-pointer-types]f(h);^
test_void_ptr.c:5:6: note: expected ‘int **’ but argument is of type ‘handle {aka int *}’void f(handle *ph) {^

那能否统一用int*做handle来规避上述问题呢?恐怕不太行,因为函数接口将形参定义成void *就是为了方便调用者传参时不用进行强制类型转换,改成int*后,就必须强转了。

怎么解决?

我试了以下方法:

  1. voidtypedef成VOID以创造新的基类型,不好使
  2. handle *typedef成phandle以显式区别2种void指针类型,也不行

看样子只能程序员自己注意了?好悲催啊!
等等,有没有可能,编译器就是不想区分void*void **呢?毕竟指针本身就是可以值传递的,为什么还要脱裤子放屁地搞个二级指针呢?

更改编程习惯

回头看我们的库接口设计,是有问题的,create返回context的地址给调用者,那么调用者在destroy执行完毕后当然有义务将记录的context置空,但是库作者为了“易用性”,选择在destroy里自己置空,而这势必要获取调用者记录context地址的指针的地址,这就“越界”了!
正确的做法是destroy只销毁context,至于调用者可能忘记置空context指针导致的内存访问问题,由调用者自己操心

总结

  1. C语言中尽量不要使用void **参数
  2. 用户态逻辑尽量用C++来写,不能改的话,至少用C++编译器来编译吧。

相关内容

热门资讯

中证A500ETF摩根(560... 8月22日,截止午间收盘,中证A500ETF摩根(560530)涨1.19%,报1.106元,成交额...
A500ETF易方达(1593... 8月22日,截止午间收盘,A500ETF易方达(159361)涨1.28%,报1.104元,成交额1...
何小鹏斥资约2.5亿港元增持小... 每经记者|孙磊    每经编辑|裴健如 8月21日晚间,小鹏汽车发布公告称,公司联...
中证500ETF基金(1593... 8月22日,截止午间收盘,中证500ETF基金(159337)涨0.94%,报1.509元,成交额2...
中证A500ETF华安(159... 8月22日,截止午间收盘,中证A500ETF华安(159359)涨1.15%,报1.139元,成交额...