g++真的很牛B么

废话不多说,先上一段代码

  1. int main()
  2. {
  3. int n = 10;
  4. int arr[n];
  5. return 0;
  6. }

很简单吧,写程序写得多了的人,一眼就能看出来,这么简单的几行语句,哪里出错了。确实这几行代码放在VS2008里面绝对会报错误:error C2057: expected constant expression. 提示是第4行的错误,于是把上面的程序改成如下格式,

  1. int main()
  2. {
  3. int arr[10];
  4. return 0;
  5. }

程序就能在vs2008中编译通过了,这一切看来似乎理所当然,顺理成章的。

但是俺突发奇想,遂拿到g++(version 4.4.3)中编译了一下,上面的代码是可以通过编译的,另外对该数组执行了几个赋值语句,在运行期也没有报任何错误。

这下我就囧了,感觉g++这个编译器要高明很多,居然能在编译期回避这个问题。但是在我的印象中,在函数内部定义声明的变量,其内存是在函数的堆栈上开辟的,而这个堆栈的大小跟系统有关。如果在函数中任意申明一个很大的内存空间,这是比较危险的,可能会导致一些溢出问题。但是g++在这里竟然支持这种语法,就着实令人费解了,难道这是个漏洞么?

不学体系结构和编译原理很久了,不知道哪位大牛能给个解答。





原创文章,版权所有。转载请注明:转载自Vimer的程序世界 [ http://www.vimer.cn ]

本文链接地址: http://www.vimer.cn/?p=1303

30 个评论 在 “g++真的很牛B么”

  1. Dante 说:

    我把代码改了一下:
    int main(int argc, const char *argv[])
    {
    int n = 10;
    int arr[n];
    printf(“%d”,sizeof(arr));
    return 0;
    }

    打印的结果是40,貌似还真动态分配了这么多空间。
    我g++的版本是3.4.5,的确有点奇怪,一会用valgrind试一下是否会有访问越界内存的问题。

    [回复]

    Dante 回复:

    再次改了一下程序:
    int main(int argc, const char *argv[])
    {
    int n = 10;
    int arr[n];
    arr[0] = 0;
    printf(“%d,%d”,sizeof(arr),arr[0]);
    return 0;
    }

    然后用valgrind扫描,结果没有报错:
    ==18902== Memcheck, a memory error detector
    ==18902== Copyright (C) 2002-2009, and GNU GPL’d, by Julian Seward et al.
    ==18902== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
    ==18902== Command: ./test
    ==18902== Parent PID: 17099
    ==18902==
    ==18902==
    ==18902== HEAP SUMMARY:
    ==18902== in use at exit: 0 bytes in 0 blocks
    ==18902== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
    ==18902==
    ==18902== All heap blocks were freed — no leaks are possible
    ==18902==
    ==18902== For counts of detected and suppressed errors, rerun with: -v
    ==18902== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 3 from 3)

    [回复]

    lr 回复:

    囧,其实我就是在想,这个问题可不可以利用一下,干干坏事……
    嗯,我很邪恶~

    [回复]

  2. Moligaloo 说:

    这个就是在栈上动态分配一块内存,与gcc提供的alloca的作用差不多,本质上就是移动 esp 指针。

    [回复]

    lr 回复:

    我说的意思,就是这个栈,函数的堆栈空间是有限的,如果在这里申请一个巨大的内存,耗尽了函数的堆栈,那不是一系列的问题就来了么?

    [回复]

    lr 回复:

    实现这个机制肯定是容易的,我就是在想安全问题

    [回复]

    erlv 回复:

    这种动态分配内存的形式,应该是在对上分配的吧。
    安全问题的话,G++应该有保证安全,估计这种变长数组和vector类型差不多。“These arrays are declared like any other automatic arrays, but with a length that is not a constant expression. ”
    所以估计用它做工具,没戏:)

    [回复]

  3. 雨碎江南 说:

    同上,(我记得)这应该是一个新特性,也就是动态分配数组空间,C99里也有这个特性.至于VS为什么报错而G++不报错,那应该是应为G++对标准的支持一向要比VS好得多…

    [回复]

  4. dutor 说:

    int n = 10;
    scanf(“%d”, &n);
    int a[n];
    printf(“%d\n”, sizeof(a));
    对于这些代码,gcc产生了大量的汇编指令用来动态地在栈上分配空间。
    我并不觉得这个特性有什么危险的啊!栈溢出的问题在静态数组上也是存在的啊!
    况且这个特性也正反应了数组的本意,即同类型的很多“变量”,对,很多,却不知多少。这样一来
    int n = 2;
    int a[n];
    就和
    int a1, a2;
    完全一样了。

    [回复]

  5. yl 说:

    用下面选项编译
    g++ -ansi -pedantic main.cc
    就会报错
    main.cc:4: 错误:ISO C++ 不允许变长数组 ‘arr’

    变长数组时gnu c允许的,不是标准C的形式,
    可以参考
    http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html#Variable-Length

    [回复]

    雨碎江南 回复:

    变长数组是c99的特性啊…

    [回复]

  6. MadPer 说:

    这个是c99的标准,和c++有什么关系?c99好像只限制c了吧?这个是g++自己扩展的,非标准吧.c++0x里没见到有这个的支持…但是c和c++的编译器既然都差不多…这个,我也就闹不轻了…

    [回复]

  7. Ricky 说:

    c专家编程里面貌似提过,c不允许这样使用,但是c++可以,g++当然也支持了

    [回复]

    MadPer 回复:

    c99都支持了,c当然也可以~~但是c++好像没有官方支持这个特性.

    [回复]

  8. lorenzo 说:

    这不是C99支持了么……

    [回复]

  9. egmkang 说:

    这是C99的内容..

    [回复]

    Terrence 回复:

    同意,C99变长数组

    [回复]

  10. egmkang 说:

    C++标准和C标准貌似在C99分道扬镳了

    [回复]

    Fangzhen 回复:

    C++第一个标准是C++98,2003年对其进行过更新,称为C++03.这个标准(C++98/03)制定的时候是考虑要将C的一个标准作为子集,当时C89已经很成熟,C99还没有完全制定完,所以就选择C89作为C++中C子集标准。当然C89和C++中的C还是有些差别的。

    [回复]

  11. egmkang 说:

    另外听说VS不会支持C99,不知道为啥,也没看出来官方的声明,只是道途听说

    [回复]

  12. shhyan 说:

    int n=5;
    int a[n];
    int b[n]={};//这种情况会报错,使用变长数组时不能初始化。
    int c[5]={};

    [回复]

    Dante 回复:

    试了一下,确实会报错毕竟不是运行时检查,所以编译的时候就直接报错了

    [回复]

  13. skydiver 说:

    这是C99的一个新特性,可变长数组(variable length array),这个是gcc的不是g++

    [回复]

  14. badming 说:

    c99支持变长数组,
    int n=10;
    {
    int data[10];
    }

    只要多一个花括号就都通用了。

    [回复]

  15. wyatt 说:

    我觉得只是一个编译优化…..

    [回复]

  16. Hacksign 说:

    标准的问题……

    [回复]

  17. EzOne 说:

    这个叫可变数组.是GNU C的扩展…

    g++ 默认用 GNU C的标准来编译
    只要在 g++ 后面加个 “-ansi”参数第一个就编译不过了

    ===========================
    你还可以试试 函数嵌套 g++一样编译的过:

    int main()
    {
    int a()
    {
    return 0;
    }
    a();
    return 0;
    }

    [回复]

    Dante 回复:

    好奇怪。。。我用g++编译失败。。
    x.cpp|9| error: a function-definition is not allowed here before ‘{‘ token
    x.cpp|13| error: `a’ was not declared in this scope

    [回复]

    EzOne 回复:

    …我搞错了…..
    这个要GCC编译…

    [回复]

我要评论

*

*