是一致的数组参数VLA吗? [英] Are conformant array parameters VLAs?

查看:194
本文介绍了是一致的数组参数VLA吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CERT的安全编码标准包含一个项目( API05- C ),鼓励使用一致的数组参数,这是我在许多代码中实现的建议(隐藏在 API05-C 提供更多信息.

很多编译器不喜欢变长数组(有充分的理由). C11将它们从必需(如在C99中)降级为可选(如果未实现,则编译器应定义__STDC_NO_VLA__). MSVC完全不支持它们. IAR将它们隐藏在开关(--vla)后面.如果您提出要求,GCC和clang会警告您有关它们(如果您要输入错误,请使用-Wvla-Werror=vla提示).

一致的数组参数不会遇到与普通"可变长度数组相同的问题;它们不会导致可变的堆栈使用情况.他们只是告诉编译器,可能在堆栈或堆中的现有数组有多大.

我的问题是,我认识的每个编译器都将一致的数组参数视为VLA.对于MSVC这样的编译器来说,这并不是什么大问题,因为我只能将宏定义为空,但是对于GCC和clang这样的编译器,我想使用一致的数组参数,但不想触发-Wvla诊断.

根据API05-C(强调):

因此,用作函数参数的数组声明可能具有作为变量或表达式的索引. array参数降级为一个指针,因此不是可变长度数组(VLA).开发人员可以使用一致的数组参数来指示数组的预期范围.此信息可能由编译器使用,或者可能被忽略.但是,此类声明对开发人员很有用,因为它们用于记录数组大小和指针之间的关系.静态分析工具还可以使用此信息来诊断潜在的缺陷.

我迫切希望做到这一点,但是我似乎找不到 C11 标准.

因此,严格根据C99/C11标准,是否符合阵列参数VLA?或者,换句话说,将数组作为参数传递是否真的将其降级为指针?

很显然,请引用规范的相关部分.

解决方案

所有声明为数组类型的参数都将转换为指针类型. VLA也不例外.

N1256(C99 + TC1 + TC2 + TC3):

6.7.5.3函数声明符(包括原型)

7必须将参数声明为类型数组"调整为类型的合格指针",其中类型限定符(如果有)是在数组类型的[]中指定的类型限定符推导.如果关键字static也出现在数组类型派生的[]中,则对于函数的每次调用,相应的实际参数的值应提供对数组第一个元素的访问,并带有at至少与size表达式指定的元素一样多.

声明为void f(int a[10]);的函数采用任何int *.声明为void f(int length, int array[length]);的函数带有intint *.

但是,您写:

我的问题是,我认识的每个编译器都将一致的数组参数视为VLA.对于MSVC这样的编译器来说,这并不是什么大问题,因为我只能将宏定义为空,但是对于GCC和clang这样的编译器,我想使用一致的数组参数,但不想触发-Wvla诊断.

好吧,这很棘手.在转换为指针之前,它是VLA,-Wvla的要点是警告在不支持VLA的编译器上无法编译的代码.如您所见,MSVC不喜欢该代码.

一致的数组参数不会遇到与普通"可变长度数组相同的问题;它们不会导致可变的堆栈使用情况.他们只是告诉编译器,可能在堆栈或堆中的现有数组有多大.

不,他们不这样做.给定void f(int a[10]);,使用空指针,指向长度为1的数组的指针等调用f是完全有效的.编译器必须支持该指针.它们只是对人类读者的提示.转换后的VLA同样如此.

CERT's Secure Coding Standard includes an item (API05-C) which encourages the use of conformant array parameters, which is a recommendation I've implemented in a lot of my code (hidden behind a macro for compilers which don't support them).

For those who don't know, a conformant array parameter is something like:

void foo(int length, char data[length]);

API05-C provides more information.

Lots of compilers don't like variable-length arrays (for good reason). C11 demotes them from required (as they were in C99) to optional (compilers should define __STDC_NO_VLA__ if they're not implemented). MSVC flat out doesn't support them. IAR hides them behind a switch (--vla). GCC and clang will warn you about them if you ask (with -Wvla, or -Werror=vla if you want an error).

Conformant array parameters don't suffer from the same problems as "normal" variable-length arrays; they don't result in variable stack usage. They just tell the compiler how big an existing array, which could be on the stack or heap, is.

My issue is that every compiler I'm aware of treats conformant array parameters as VLAs. This isn't such a big deal for compilers like MSVC since I can just define my macro to nothing, but for compilers like GCC and clang I want to use conformant array parameters but don't want to trigger -Wvla diagnostics.

According to API05-C (emphasis added):

Consequently, an array declaration that serves as a function argument may have an index that is a variable or an expression. The array argument is demoted to a pointer and is consequently not a variable length array (VLA). Conformant array parameters can be used by developers to indicate the expected bounds of the array. This information may be used by compilers, or it may be ignored. However, such declarations are useful to developers because they serve to document relationships between array sizes and pointers. This information can also be used by static analysis tools to diagnose potential defects.

I desperately want this to be true, but I can't seem to find the relevant parts of the C99 or C11 standards.

So, based strictly on the C99/C11 standards, are conformant array parameters VLAs? Or, to put it another way, does passing an array as an argument really demote it to a pointer?

Obviously, please cite the relevant parts of the specification(s).

解决方案

All parameters declared as array types are transformed to pointer types. VLAs are no exception.

N1256 (C99+TC1+TC2+TC3):

6.7.5.3 Function declarators (including prototypes)

7 A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

A function declared void f(int a[10]); takes any int *. A function declared void f(int length, int array[length]); takes an int and a int *.

However, you write:

My issue is that every compiler I'm aware of treats conformant array parameters as VLAs. This isn't such a big deal for compilers like MSVC since I can just define my macro to nothing, but for compilers like GCC and clang I want to use conformant array parameters but don't want to trigger -Wvla diagnostics.

Well, it's tricky. It is a VLA before it is transformed to a pointer, and the point of -Wvla was to warn about code that would fail to compile on compilers that do not support VLAs. As you've seen, MSVC doesn't like the code.

Conformant array parameters don't suffer from the same problems as "normal" variable-length arrays; they don't result in variable stack usage. They just tell the compiler how big an existing array, which could be on the stack or heap, is.

No, they do not do that. Given void f(int a[10]);, it is perfectly valid to call f with a null pointer, with a pointer to an array of length 1, etc. The compiler must support that. They only serve as a hint to human readers. The same applies to transformed VLAs.

这篇关于是一致的数组参数VLA吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆