如下代码:
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 9
因为 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 有没有什么更高级的特性就不清楚了
|