Xét đoạn mã sau:Tại sao GCC phân bổ không gian ngăn xếp riêng biệt cho các công đoàn địa phương trong các phạm vi khác nhau?
#include <stdlib.h>
#ifndef TRY
#define TRY struct
#endif
TRY testme
{
int one;
int two;
char three;
int four;
};
int
main (void)
{
{
volatile TRY testme one;
one.one = 2;
one.three = 7;
}
{
volatile TRY testme twos;
twos.one = 3;
}
{
volatile TRY testme one;
one.one = 4;
}
{
volatile TRY testme twos;
twos.one = 5;
}
{
volatile TRY testme twos;
twos.one = 6;
}
{
volatile TRY testme twos;
twos.one = 6;
}
return EXIT_SUCCESS;
}
Biên soạn như là cho x86 được (có nghĩa là testme là một struct), ngăn xếp kích thước trình biên dịch phân bổ cho chính là 16 byte.
$ gcc -g -O2 test.c -o test
$ objdump -d ./test | ./checkstack.pl i386 | grep main
16 main
Tuy nhiên, biên soạn với TRY định nghĩa công đoàn (có nghĩa là testme là một liên minh), ngăn xếp kích thước trình biên dịch phân bổ cho chính là 32 byte:
$ gcc -DTRY=union -g -O2 test.c -o test
$ objdump -d ./test | ./checkstack.pl i386 | grep main
Hơn nữa, bất kỳ phiên bản bổ sung của struct/union được định nghĩa trong phạm vi bổ sung, sẽ tạo ra phân bổ stack lớn hơn khi sử dụng một union, nhưng sẽ không mở rộng phân bổ stack khi được sử dụng như một struct.
Bây giờ, điều này không có ý nghĩa - công đoàn nên mất ít không gian ngăn xếp, nếu có, không nhiều hơn, sau đó một cấu trúc với các lĩnh vực tương tự!
Dường như GCC đối xử với các công đoàn như được sử dụng đồng thời ngay cả khi ở các phạm vi khác nhau, nhưng không làm tương tự cho các cấu trúc.
Một số chi tiết làm rõ:
dễ bay hơi được sử dụng để ngăn chặn các trình biên dịch từ tối ưu hóa đi những bài tập. Mất biến động và biên dịch không có tối ưu hóa sẽ tạo ra kết quả tương tự.
Ngay cả khi testme là một cấu trúc có liên minh là một trong các thành viên, thì hành vi tương tự cũng được quan sát. Nói cách khác - nó là đủ mà một trong những thành viên của một cấu trúc là một liên minh cho GCC để phân bổ stack riêng biệt.
Trình biên dịch là phiên bản gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5) nhưng các phiên bản GCC khác cho các kiến trúc khác cũng cho thấy hành vi tương tự.
checkstack.pl chỉ cần tìm kiếm đầu ra objdump cho các hướng dẫn được sử dụng để cấp phát ngăn xếp (phụ cho con trỏ ngăn xếp).
Câu hỏi của tôi:
- Tại sao GCC làm điều này? đây có phải là lỗi hay có lý do cho hành vi này không?
- Giả sử đây không phải là lỗi, có cách nào đó để giải quyết vấn đề này và buộc GCC phân bổ ngăn xếp cho các mảng giống như công đoàn.
Làm rõ: Câu hỏi của tôi không phải là lý do tại sao cấu trúc hoặc công đoàn có kích thước lớn hơn so với kích thước của nó. Tôi hiểu lý do là đệm cho căn chỉnh. Vấn đề của tôi là trình biên dịch phân bổ nhiều khung stack cho các trường hợp khác nhau của union mặc dù chúng được định nghĩa trong các phạm vi khác nhau trong khi nó không nên và thực sự không làm tương tự cho một struct với cùng các trường.
Cảm ơn!
lẽ công đoàn không cũng được tối ưu hóa tại '-O2' (chưa)? Có một cái nhìn tại mã assembler được tạo ra. Ngoài ra, hãy thử tắt 'strict-aliasing'. Oh, và thử GCC hiện tại. –
Bạn đã xem xét [câu hỏi này] (http://stackoverflow.com/questions/8453881/sizeof-union-larger-than-expected-how-does-type-alignment-take-place-here) và [ cái này] (http://stackoverflow.com/questions/7212585/why-is-my-unions-size-bigger-than-i-expected)? Nó có vẻ là một vấn đề về ràng buộc padding và liên kết – Coren
@ Anony-Mousse -fno-strict-aliasing tạo ra kết quả tương tự. Tôi đang xây dựng GCC mới nhất để kiểm tra. – gby