如下代码:
void F(char x[10]) { char y[10]; y[11] = 0; // warning: array index 11 is past the end of the array x[11] = 0; }
数组 y 越界访问时编译器会给出告警,但 x 却不会,因为编译器会忽略参数数组的长度,是否有方案可让编译器检查参数数组的长度?
![]() | 1 Noicdi 2023-03-13 12:10:37 +08:00 via iPhone 你把 y 修改正确,x 依旧保持错误,看看会不会有警告呢? 我下意识的猜想是,按顺序警告 |
2 Thymolblue 2023-03-13 12:11:58 +08:00 via Android 好像是你这个函数并不会把数组长度这个信息传进去。下面这样可以把数组的长度传进去。我的编译器是 MinGW 7.3.0 template <typename T> void foo(T &t) { // 可以直接使用迭代器迭代整个数组 for (auto &item: t) { item = 0; } t[11] = 0; // 传一个长度为 10 的数组这里会触发警告 } |
3 Thymolblue 2023-03-13 12:12:29 +08:00 via Android @Thymolblue 手机编辑排版乱了,见谅 |
4 sosilver 2023-03-13 12:12:54 +08:00 via Android 函数参数是 T*,不是 T[N],试试传 reference |
![]() | 5 geelaw 2023-03-13 12:19:04 +08:00 ![]() 因为 C 的缘故,void foo(char x[10]) 和 void foo(char *x) 是一个意思。要传递数组引用而不是指针的话,应该 void foo(char (&x)[10])。 |
6 VZXXBACQ 2023-03-13 12:21:23 +08:00 这种情况传递引用可解 |
![]() | 7 ALLROBOT 2023-03-13 12:25:29 +08:00 |
8 SMGdcAt4kPPQ 2023-03-13 12:33:27 +08:00 via Android 用 std::array |
![]() | 9 tyzandhr 2023-03-13 12:34:00 +08:00 via Android 为什么不用 span 呢? |
![]() | 10 tool2d 2023-03-13 12:36:57 +08:00 还是用 std::vector 中括号操作符重载吧,重载在 debug 时候检测一下越界问题。 这裸指针直接赋值,也太吓人了。 |
![]() | 11 yolee599 2023-03-13 12:38:18 +08:00 via Android 形参的 x[10] 完全等同于 *x ,指针不能确定数组大小 |
![]() | 12 yolee599 2023-03-13 12:40:44 +08:00 via Android 通常做法是再加一个形参来描述数组大小: void F(char *x, int len) |
13 leonshaw 2023-03-13 12:42:51 +08:00 数组、std::array, std::span, std::vector 越界都是 UB ,告警是编译器的行为。 |
![]() | 14 tool2d 2023-03-13 12:48:20 +08:00 |
15 nightwitch 2023-03-13 13:39:33 +08:00 via Android 没什么特殊理由不要用 c style arr ,用 std::array 有效消除这种问题 |
![]() | 16 pipapa 2023-03-13 14:08:04 +08:00 有工具是可以扫描出来的,这种应该编码应该强制传长度参数进去 |
![]() | 17 rozbo 2023-03-13 14:59:17 +08:00 一个指针哪来的长度。。你得传数组的引用 |
18 daveh 2023-03-13 15:39:06 +08:00 via iPhone 试试用 CLion ,Inspections - Data flow analysis 里面有专门的数组越界检查,能查出问题。 另外确实如前面有 V 友所说,函数入参并不是你想的那样,有可能你传入的数组够长,所以后一个编译器没法识别出问题。 但 CLion 的 Data flow analysis ,会识别调用 F(x)的上下文,如果你传入数组 x 不够长,后一个也会报数组越界;如果 x 长度够则不报问题;如果没有 F 的函数调用,也不报问题。 |
![]() | 19 LuffyWong 2023-03-13 17:44:24 +08:00 最近刚好在读 the c++ programming language, 刚好 12.2.2 讲到了这个 |
20 lzyliangzheyu 2023-03-13 23:24:45 +08:00 via Android 数组传参会退化为指针,会丢失数组的大小信息,至少 C 是这样的,一般都是把数组当成指针传过去,至于数组的大小再单独一个参数传过去,至于 CPP 有没有什么更高级的特性就不清楚了 |