2012-07-04 37 views
5

Tại sao điều đó xảy ra? Mã hoạt động và không tạo ra cảnh báo với GCC 4.7 trên Linux và MSVC++ 2010 trên Windows. Tuy nhiên, trên ideone.com nó crashes với SIGILL. Hành vi không xác định có liên quan ở đây không?Tại sao mã C++ này nhận được SIGILL trên ideone.com?

#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")); 
} 

Trả lời

1

Tôi đã nhận lỗi với GCC 4.4.6:

test.cpp: In function ‘void print(int, ...)’: 
test.cpp:59: warning: cannot receive objects of non-POD type ‘struct mt’ through ‘...’; call will abort at runtime 
test.cpp: In function ‘int main()’: 
test.cpp:83: warning: cannot pass objects of non-POD type ‘struct mt’ through ‘...’; call will abort at runtime 
test.cpp:83: warning: cannot pass objects of non-POD type ‘struct mt’ through ‘...’; call will abort at runtime 
test.cpp:83: warning: cannot pass objects of non-POD type ‘struct mt’ through ‘...’; call will abort at runtime 
test.cpp:83: warning: cannot pass objects of non-POD type ‘struct mt’ through ‘...’; call will abort at runtime 
$ g++ --version 
g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) 

Bạn không thể vượt qua struct s qua varargs thông số chức năng, thay vì vượt qua con trỏ:

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() 
{ 
    mt mt1(2); 
    mt mt2(4.2); 
    mt mt3('a'); 
    mt mt4("Hello"); 
    print(4, &mt1, &mt2, &mt3, &mt4); 
} 

nào hoạt động tốt trên hệ thống của tôi :

$ ./a.out 
2 
4.2 
a 
Hello 
+0

Tôi đã nghĩ rằng người ta có thể vượt qua bất cứ điều gì đó là POD (xem C++ 03, 5.2.2.7, "_or class type_"). Và 'struct mt' trông POD với tôi, bởi vì (a) nó không có thành viên không phải POD, (b) nó không có một toán tử gán bản sao do người dùng định nghĩa và (c) nó không có người dùng -dấu hủy định nghĩa (xem Điều 9). Khoản khấu trừ này có sai không? –

+0

@AndreyVihrov Varargs là một cái gì đó của một hack và không di động (như bạn đã phát hiện ra). Sử dụng 'std :: ' hoặc một số lớp sưu tập khác để truyền đối tượng giữa các phương thức. – trojanfoe

+2

Tôi không đồng ý. Varargs là di động, bởi vì chúng chính thức là một phần của cả C và C++ tiêu chuẩn :-) –

Các vấn đề liên quan