为什么这个C++代码在ideone.com上获得SIGILL?

And*_*rov 5 c++ gcc

为什么会这样?该代码在Linux上运行GCC 4.7,在Windows上运行MSVC++ 2010时不会生成警告.然而,在ideone.com上,它崩溃SIGILL.这里涉及到未定义的行为吗?

#include <iostream>
#include <cstdarg>

using namespace std;

enum types
{
    INT,
    DOUBLE,
    CHAR,
    STRING
};

struct mt
{
    types type;

    union
    {
        int         i;
        double      d;
        char        c;
        const char *s;
    } val;

    mt(int i)
        : type(INT)
    {
        val.i = i;
    }

    mt(double d)
        : type(DOUBLE)
    {
        val.d = d;
    }

    mt(char c)
        : type(CHAR)
    {
        val.c = c;
    }

    mt(const char *s)
        : type(STRING)
    {
        val.s = s;
    }
};

void print(int n, ...)
{
    va_list ap;

    va_start(ap, n);

    for (int i = 0; i < n; i++)
    {
        mt x(va_arg(ap, mt));

        switch (x.type)
        {
        case INT:
            cout << x.val.i << endl;
            break;
        case DOUBLE:
            cout << x.val.d << endl;
            break;
        case CHAR:
            cout << x.val.c << endl;
            break;
        case STRING:
            cout << x.val.s << endl;
            break;
        }
    }

    va_end(ap);
}

int main()
{
    print(4, mt(2), mt(4.2), mt('a'), mt("Hello"));
}
Run Code Online (Sandbox Code Playgroud)

tro*_*foe 1

我在 GCC 4.4.6 中遇到错误:

\n\n
test.cpp: In function \xe2\x80\x98void print(int, ...)\xe2\x80\x99:\ntest.cpp:59: warning: cannot receive objects of non-POD type \xe2\x80\x98struct mt\xe2\x80\x99 through \xe2\x80\x98...\xe2\x80\x99; call will abort at runtime\ntest.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\ntest.cpp:83: warning: cannot pass objects of non-POD type \xe2\x80\x98struct mt\xe2\x80\x99 through \xe2\x80\x98...\xe2\x80\x99; call will abort at runtime\ntest.cpp:83: warning: cannot pass objects of non-POD type \xe2\x80\x98struct mt\xe2\x80\x99 through \xe2\x80\x98...\xe2\x80\x99; call will abort at runtime\ntest.cpp:83: warning: cannot pass objects of non-POD type \xe2\x80\x98struct mt\xe2\x80\x99 through \xe2\x80\x98...\xe2\x80\x99; call will abort at runtime\ntest.cpp:83: warning: cannot pass objects of non-POD type \xe2\x80\x98struct mt\xe2\x80\x99 through \xe2\x80\x98...\xe2\x80\x99; call will abort at runtime\n$ g++ --version\ng++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)\n
Run Code Online (Sandbox Code Playgroud)\n\n

struct您不能通过varargs 函数参数传递s,而是传递指针:

\n\n
void print(int n, ...)\n{\n    va_list ap;\n\n    va_start(ap, n);\n\n    for (int i = 0; i < n; i++)\n    {\n        mt *x(va_arg(ap, mt *));\n\n        switch (x->type)\n        {\n        case INT:\n            cout << x->val.i << endl;\n            break;\n        case DOUBLE:\n            cout << x->val.d << endl;\n            break;\n        case CHAR:\n            cout << x->val.c << endl;\n            break;\n        case STRING:\n            cout << x->val.s << endl;\n            break;\n        }\n    }\n\n    va_end(ap);\n}\n\nint main()\n{\n    mt mt1(2);\n    mt mt2(4.2);\n    mt mt3(\'a\');\n    mt mt4("Hello");\n    print(4, &mt1, &mt2, &mt3, &mt4);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的系统上运行良好:

\n\n
$ ./a.out\n2\n4.2\na\nHello\n
Run Code Online (Sandbox Code Playgroud)\n

  • 我不同意。Varargs 是可移植的,因为它们是 C 和 C++ 标准的正式一部分:-) (2认同)
  • @Andrey - POD 结构必须是*聚合*。这也不包括用户定义的构造函数(8.5.1)。 (2认同)