[Programming] gỡ rối giùm mình chương trình C |
19/02/2009 00:59:47 (+0700) | #1 | 169926 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
Chào các bạn,
Mình có chương trình C đơn giản thế này mà không hiểu sao khi biên dịch bằng gcc-4.x rồi chạy thì nó cứ đứng khựng lại, không biết sai chỗ nào?
Code:
void weird_print(char *str)
{
char buffer[100];
int n=0;
for (n=0; n<=100;n++)
buffer[n]=str[n];
printf("%s\n", buffer);
}
int main(int argc, char *argv[])
{
if (argc>1) weird_print(argv[1]);
return 0;
}
|
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 01:01:53 (+0700) | #2 | 169927 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
Test case ra sao? "Đứng khựng lại" là sao? Không có gì output ra màn hình? |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 01:05:40 (+0700) | #3 | 169928 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@lamer: đúng rồi đó bạn. Thí dụ mình chạy thế này:
Code:
$ ./test `perl -e 'print "A" x 10'`
Lẽ ra nó phải xuất ra 10 chữ A, nhưng đằng này nó đứng luôn, không xuất gì ra màn hình. strace cũng không thấy gì hết, cứ đứng im. |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 01:47:11 (+0700) | #4 | 169939 |
|
secmask
Elite Member
|
0 |
|
|
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
|
|
tớ test với gcc version 4.1.2 20071124 vẫn chạy bình thường
[secmask@secmask-home setup]$ ./wprint
[secmask@secmask-home setup]$ ./wprint `perl -e 'print "A" x 10'`
AAAAAAAAAA
|
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 01:50:09 (+0700) | #5 | 169940 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@secmask: chạy thử lại nhiều lần xem sao? Xem có lần nào bị đứng im không? |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 02:05:05 (+0700) | #6 | 169941 |
|
secmask
Elite Member
|
0 |
|
|
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
|
|
choc_ wrote:
@secmask: chạy thử lại nhiều lần xem sao? Xem có lần nào bị đứng im không?
tớ lặp lại gần chục lần vẫn vậy . |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 06:26:50 (+0700) | #7 | 169979 |
choc_
Member
|
0 |
|
|
Joined: 27/01/2009 06:46:01
Messages: 122
Offline
|
|
@secmask: có thể gcc của mình nó tạo kết quả khác. Để thuận tiện, mình gửi binary lên đây cho các bạn xem thử: http://www.mediafire.com/?ytodbt4nhwl
Nhớ cẩn thận nha, mình ít bao giờ chạy binary lạ mà không xem xét trước lắm. |
|
|
|
|
[Question] gỡ rối giùm mình chương trình C |
19/02/2009 07:09:10 (+0700) | #8 | 169980 |
|
secmask
Elite Member
|
0 |
|
|
Joined: 29/10/2004 13:52:24
Messages: 553
Location: graveyard
Offline
|
|
choc_ wrote:
Chào các bạn,
Mình có chương trình C đơn giản thế này mà không hiểu sao khi biên dịch bằng gcc-4.x rồi chạy thì nó cứ đứng khựng lại, không biết sai chỗ nào?
Code:
void weird_print(char *str)
{
char buffer[100];
int n=0;
for (n=0; n<=100;n++)
buffer[n]=str[n];
printf("%s\n", buffer);
}
int main(int argc, char *argv[])
{
if (argc>1) weird_print(argv[1]);
return 0;
}
thử bỏ dấu "=" ở chỗ này " for (n=0; n<=100;n++)" đi coi, chắc nó overwrite lên "n" mất rồi.
|
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 09:38:23 (+0700) | #9 | 169992 |
mfeng
Researcher
|
Joined: 29/10/2004 15:16:29
Messages: 243
Offline
|
|
Tớ dịch trên CentOS, gcc-4.x thì đúng có hiện tượng trên, chương trình bị lặp không thoát được.
Disassemble bằng gdb thấy có đoạn này:
Code:
mov 0xfffffffc(%ebp),%eax ;lấy giá trị n từ bộ nhớ ra thanh ghi eax.
.... ; thực hiện đọc 1 byte từ str & copy sang buffer.
addl $0x1, 0xfffffffc(%ebp) ; tăng giá trị nằm trong vùng nhớ n lên 1 & so sánh
cmp $0x64, 0xfffffffc(%ebp)
jle ...
Stack của hàm weird_print ở đây nó thế này:
buffer[0-100]: từ [ebp-0x68] đến [ebp-0x05];
n: bắt đầu từ [ebp-0x04].
Khi ghi vào byte thứ 100 (ebp-0x04), vùng nhớ này trùng với địa chỉ của n nên giá trị n bị ghi đè.
Tuy nhiên, điều lý thú lại như thế này, tớ viết thêm 2 dòng code in địa chỉ của n & buffer[100]:
Code:
void weird_print(char *str)
{
char buffer[100];
int n=0;
printf("Address of n:%p\n",&n);
printf("Address of buffer[100]:%p\n",&buffer[100]);
for (n=0; n<=100;n++)
buffer[n]=str[n];
printf("%s\n", buffer);
}
Thì đoạn code kiểm tra điều kiện <=100 nó lại như sau:
Code:
mov 0xffffff98(%ebp), eax
....
[color=red]add $0x1, %eax
mov %eax, 0xffffff98(%ebp)
mov 0xffffff98(%ebp), %eax[/color]
cmp $0x64, %eax
jle ....
Stack map có thứ tự như sau:
n: [ebp-68];
buffer[0-100]: [ebp-64]
Vì thứ tự biến bị thay đổi trên stack, n đứng dưới buffer nên n không thể bị ghi đè. Nếu giả sử stack vẫn như cũ thì cũng không bị ghi đè bới hai dòng code màu đỏ ở trên. Vì thế chương trình không bị loop nữa . |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/02/2009 11:59:37 (+0700) | #10 | 170011 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
Bug, thông báo cho GCC đi mọi người. |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
20/02/2009 02:46:20 (+0700) | #11 | 170107 |
TQN
Elite Member
|
0 |
|
|
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
|
|
Bug à, thằng compiler muốn sinh mã ra sao thì tùy nó chứ, đứng trước đứng sau trong stack có quan trong đâu hè ? |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
20/02/2009 09:34:30 (+0700) | #12 | 170166 |
lamer
Elite Member
|
0 |
|
|
Joined: 26/02/2008 13:28:49
Messages: 215
Offline
|
|
À, cái này thì không đồng ý.
1. Để tránh lỗi BO thì các trình dịch hiện đại sẽ đặt các biến đơn ở trước các bộ đệm. Khi bộ đệm bị trà thì giá trị các biến đơn có thể vẫn được giữ nguyên.
2. Việc đặt trước hay sau cũng phải thống nhất. Lẽ nào chỉ vì hai dòng lệnh không liên quan đến việc khai báo và khởi tạo biến lại làm thay đổi vị trí của hai biến này? |
|
|
|
|
[Question] Re: gỡ rối giùm mình chương trình C |
19/03/2009 06:22:15 (+0700) | #13 | 173706 |
TQN
Elite Member
|
0 |
|
|
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
|
|
Cái này cũng không phải là lỗi. Thử xóa dòng
Code:
printf("Address of buffer[100]:%p\n",&buffer[100]);
đi và compile lại thử xem.
Trên gcc thì tui không biết, nhưng với VC++ 200x trở đi, compiler có thể detect các risk nguy hiểm trong hàm và tự hoán đổi vị trí của biến trong stack.
Trong trường hợp này ta thấy có hai risk: printf và truy xuất &buffer.
|
|
|
Users currently in here |
1 Anonymous
|
|
Powered by JForum - Extended by HVAOnline
hvaonline.net | hvaforum.net | hvazone.net | hvanews.net | vnhacker.org
1999 - 2013 ©
v2012|0504|218|
|
|