【问题标题】:Why is clang optimizing out my array even when using -O0 flag?为什么即使使用 -O0 标志也会优化我的数组?
【发布时间】:2026-01-22 18:05:02
【问题描述】:

我正在尝试使用 GDB 调试以下 C 程序:

// Program to generate a user specified number of 
// fibonacci numbers using variable length arrays
// Chapter 7  Program 8   2013-07-14

#include <stdio.h>

int main(void)
{
    int i, numFibs;
    printf("How many fibonacci numbers do you want (between 1 and 75)?\n");
    scanf("%i", &numFibs);

    if (numFibs < 1 || numFibs > 75)
    {
        printf("Between 1 and 75 remember?\n");
        return 1;
    }

    unsigned long long int fibonacci[numFibs];

    fibonacci[0] = 0;  // by definition
    fibonacci[1] = 1;  // by definition

    for(i = 2; i < numFibs; i++)
        fibonacci[i] = fibonacci[i-2] + fibonacci[i-1];

    for(i = 0; i < numFibs; i++)
        printf("%llu ", fibonacci[i]);

    printf("\n");

    return 0;
}

我遇到的问题是尝试使用以下代码编译代码时: clang -ggdb3 -O0 -Wall -Werror 7_8_FibonacciVarLengthArrays.c

当我尝试在创建的 a.out 文件上运行 gdb 时,我正在逐步执行程序。在 fibonacci[] 数组被标定后的任何时候,我都会输入: 当地人信息 结果显示fibonacci &lt;value optimized out&gt;(直到我的for循环的第一次迭代之后),然后导致斐波那契为程序的其余部分保存地址0xbffff128(但取消引用该地址似乎不包含任何有意义的数据)。

我只是很困惑,为什么当使用 -O0 标志时,clang 似乎正在优化这个数组?

我可以使用 gcc 来编译这段代码,并且在使用 GDB 时值会按预期显示...... 有什么想法吗?

谢谢。

【问题讨论】:

  • (Un)幸运的是,-O0 并不意味着“关闭所有优化”。嗯,确实如此,但clang 似乎并不在意。有些优化无法关闭,例如。 G。无论如何,1 + 2 将始终是恒定折叠的。显然,这是其中一种情况。

标签: c optimization gcc gdb clang


【解决方案1】:

您没有提及您使用的是哪个版本的clang。我尝试了 3.2 和最近的 SVN 安装 (3.4)。

两个版本生成的代码看起来和我很相似,但调试信息不​​同。当我尝试在 gdb 中检查斐波那契时,clang 3.2(来自默认的 ubuntu 13.04 安装)会产生错误:

fibonacci = <error reading variable fibonacci (DWARF-2 expression error: DW_OP_reg operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.)>

在使用 clang 3.4 编译的代码中,一切正常。在这两种情况下,数组都没有“优化”;它显然是在堆栈上分配的。

所以我怀疑你看到的奇怪之处更多地与调试信息的发射有关,而不是与实际代码有关。

【讨论】:

    【解决方案2】:

    gdb 还不支持调试堆栈分配的可变长度数组。见https://sourceware.org/gdb/wiki/VariableLengthArray

    使用编译时间常数或 malloc 分配斐波那契,以便 gdb 可以看到它。

    另见GDB reports "no symbol in current context" upon array initialization

    【讨论】:

      【解决方案3】:

      clang 根本没有“优化”数组!该数组被声明为堆栈上的可变长度数组,因此在达到其声明时必须显式分配(使用类似于alloca() 使用的技术)。在该过程完成之前,数组的起始地址是未知的。

      【讨论】: