C++ 中固定长度的数组作为参数,编译器能越界检查吗

2023-03-13 11:40:42 +08:00
 iqoo

如下代码:

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 却不会,因为编译器会忽略参数数组的长度,是否有方案可让编译器检查参数数组的长度?

1938 次点击
所在节点    程序员
20 条回复
Noicdi
2023-03-13 12:10:37 +08:00
你把 y 修改正确,x 依旧保持错误,看看会不会有警告呢?
我下意识的猜想是,按顺序警告
Thymolblue
2023-03-13 12:11:58 +08:00
好像是你这个函数并不会把数组长度这个信息传进去。下面这样可以把数组的长度传进去。我的编译器是 MinGW 7.3.0
template <typename T>
void foo(T &t)
{
// 可以直接使用迭代器迭代整个数组
for (auto &item: t)
{
item = 0;
}
t[11] = 0; // 传一个长度为 10 的数组这里会触发警告
}
Thymolblue
2023-03-13 12:12:29 +08:00
@Thymolblue 手机编辑排版乱了,见谅
sosilver
2023-03-13 12:12:54 +08:00
函数参数是 T*,不是 T[N],试试传 reference
geelaw
2023-03-13 12:19:04 +08:00
因为 C 的缘故,void foo(char x[10]) 和 void foo(char *x) 是一个意思。要传递数组引用而不是指针的话,应该 void foo(char (&x)[10])。
VZXXBACQ
2023-03-13 12:21:23 +08:00
这种情况传递引用可解
ALLROBOT
2023-03-13 12:25:29 +08:00
@geelaw C++还有这种用法,写起来真是麻烦。。。

请问一般开发建议用什么标准的 C++?虽然写起来是麻烦了点,但跑起来挺快的
SMGdcAt4kPPQ
2023-03-13 12:33:27 +08:00
用 std::array
tyzandhr
2023-03-13 12:34:00 +08:00
为什么不用 span 呢?
tool2d
2023-03-13 12:36:57 +08:00
还是用 std::vector 中括号操作符重载吧,重载在 debug 时候检测一下越界问题。

这裸指针直接赋值,也太吓人了。
yolee599
2023-03-13 12:38:18 +08:00
形参的 x[10] 完全等同于 *x ,指针不能确定数组大小
yolee599
2023-03-13 12:40:44 +08:00
通常做法是再加一个形参来描述数组大小:
void F(char *x, int len)
leonshaw
2023-03-13 12:42:51 +08:00
数组、std::array, std::span, std::vector 越界都是 UB ,告警是编译器的行为。
tool2d
2023-03-13 12:48:20 +08:00
5 楼的代码很完美,但我总觉得看着好奇怪哦。

nightwitch
2023-03-13 13:39:33 +08:00
没什么特殊理由不要用 c style arr ,用 std::array 有效消除这种问题
pipapa
2023-03-13 14:08:04 +08:00
有工具是可以扫描出来的,这种应该编码应该强制传长度参数进去
rozbo
2023-03-13 14:59:17 +08:00
一个指针哪来的长度。。你得传数组的引用
daveh
2023-03-13 15:39:06 +08:00
试试用 CLion ,Inspections - Data flow analysis 里面有专门的数组越界检查,能查出问题。
另外确实如前面有 V 友所说,函数入参并不是你想的那样,有可能你传入的数组够长,所以后一个编译器没法识别出问题。
但 CLion 的 Data flow analysis ,会识别调用 F(x)的上下文,如果你传入数组 x 不够长,后一个也会报数组越界;如果 x 长度够则不报问题;如果没有 F 的函数调用,也不报问题。
LuffyWong
2023-03-13 17:44:24 +08:00
最近刚好在读 the c++ programming language, 刚好 12.2.2 讲到了这个
lzyliangzheyu
2023-03-13 23:24:45 +08:00
数组传参会退化为指针,会丢失数组的大小信息,至少 C 是这样的,一般都是把数组当成指针传过去,至于数组的大小再单独一个参数传过去,至于 CPP 有没有什么更高级的特性就不清楚了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/923540

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX