【问题标题】:Variable length array with GCC flag "-Wlarger-than=len"带有 GCC 标志“-Wlarger-than=len”的可变长度数组
【发布时间】:2016-05-20 19:01:14
【问题描述】:

我真的不知道哪个应该是正确的标题,但我会尽力解释它,请耐心等待。

今天我发现了这个GCC flag =>> -Wlarger-than=len:

Warn whenever an object of larger than len bytes is defined. 

所以我决定试一试。让我们看看下面的程序:

#include <stdio.h>
#include <string.h>

int main(void){
    char ptr[12] = "Mississippi";
    size_t len1 = sizeof ptr;

    printf("Len1 = %zu\n", len1);

    char a[len1];
    strcpy(a, ptr);

    printf("\nA = %s\n", a);
}

作为输出返回:

Len1 = 12

A = Mississippi

所以程序看起来不错,但是如果我用len == 10-Wlarger-than=len 标志打开而不是12:

gcc -Wall -Wextra -Werror -Wlarger-than=10 program.c -o program

当我期望 12 时,我得到了 16:

program.c:5:14: error: size of ‘ptr’ is 12 bytes [-Werror=larger-than=]
         char ptr[12] = "Mississippi";
              ^~~
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
         char a[len1];
              ^
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]

为什么会这样?我对此感到困惑,因为这一行:

char a[len1];

我认为它会是:

char a[12];

如果我将size_t len1 = sizeof ptr; 更改为size_t len1 = strlen(ptr) + 1;,也会发生同样的事情

【问题讨论】:

  • 迟到的评论,但 gcc 有这个标志 -Wvla-larger-than= 会警告您有关 vla 大小的信息。

标签: c gcc


【解决方案1】:

您的a 是一个可变长度数组 (VLA)。显然,编译器无法预测 VLA 的未来运行时大小,这意味着 -Wlarger-than=len 选项不能也不会发出适用于 VLA 数组本身的警告。尽管您有预期,但您看到的警告并不直接适用于您的数组 a,也不会由 a 本身的大小触发。

可变长度数组通过一些依赖于实现的内部数据类型在底层实现,在 GCC 中它的大小恰好为 16。可以猜测,在您的平台上,这种内部数据类型包括一个指向数组内存的 8 字节指针以及 8 字节运行时大小信息。这就是尺寸 16 的由来。如果您对代码进行更多实验,您会发现大小根本不取决于 len1 的值。大小始终为 16。

您收到的警告适用于该内部类型的特定堆栈分配匿名对象。这就是错误消息显示‘({anonymous})’ 而不是a 的原因。您基本上可以说,使用len 小于16 的-Wlarger-than=len 选项将始终触发每个VLA 的诊断。

即你的

char a[len1];

不等于

char a[12];

正如你所相信的那样。它实际上相当于

struct anonymous_t {
  char *data;
  size_t size;
} anonymous = { alloca(len1), len1 };

每次访问a[i] 时,编译器实际上都会访问anonymous.data[i]。您看到的消息抱怨anonymous 的大小,而不是a 的大小。

【讨论】:

  • 我刚刚注意到这里-Wlarger-than=len,len 应该是&gt;= 16 并且工作正常,如果我说类似char ptr[] = "Arnold-Schwarzenegger"; 的话,唯一的警告将是error: size of ‘ptr’ is 22 bytes
  • 我认为不必分配指针,甚至不必分配长度。也许只是对齐需要 8 或 16 字节对齐,因此 VLA 的最小大小将是 16(如果存储了长度,则为 8)。查看生成的代码应该会澄清。 (或者也许有一些关于 gcc 如何在该架构上管理 VLA 的信息)
  • Gcc 有这个 Wvla-larger-than= 会警告 vla 大小。
猜你喜欢
  • 2020-09-01
  • 2014-04-30
  • 2015-10-21
  • 2020-10-26
  • 2011-04-28
  • 2020-11-20
  • 2014-07-27
  • 1970-01-01
相关资源
最近更新 更多