[Programming] Thảo luận về địa chỉ vùng nhớ Stack |
07/01/2008 18:55:09 (+0700) | #1 | 108880 |
|
zThienLongz
Member
|
0 |
|
|
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
|
|
Mình có 1 vài vấn đề cần mọi người giúp đỡ thảo luận. Trước hết xét 2 đoạn mã sau:
Code 1:
Code:
#include"iostream"
using namespace std;
void display(){
int y=-2;
cout<<&y<<endl;
}
int main(){
int x=-1;
cout<<&x<<" ";
display();
return 0;
}
Code 2:
Code:
#include"iostream"
using namespace std;
void display(){
int y=-2;
cout<<&y<<endl;
}
void hien(){
display();
}
int main(){
int x=-1;
cout<<&x<<" ";
hien();
return 0;
}
Mình complier của 2 đoạn mã và chạy đi chạy lại chúng nhiều lần thì thấy khoảng cách địa chỉ của x và y trong 2 đoạn mã là không giống nhau . VD như trên máy mình thì trong Code 1 là 44 còn Code 2 là 60.
Thứ 1: Tại sao khoảng cách địa chỉ của x, y lớn đến vậy, -> có 1 vùng nhớ nằm giữa 2 biến x, y.
Thứ 2: Tại sao tại sao khoảng cách địa chỉ của 2 đoạn mã là khác nhau.
Còn đây là lập luận của mình về 2 vấn đề trên mọi người xem có đúng không:
Như ta đã biết 1 chương trình gồm nhiều hàm được tạo lên, mỗi 1 hàm tương ứng với 1 stack frame. Mỗi khi 1 hàm được gọi thì 1 stack frame được tạo ra, và khi hàm đó trở về (function return ) thì stack frame của hàm đó bị giải phóng.
Mỗi 1 stack frame chứa 3 thông tin:
1. Tham số truyền vào
2. Biến local của hàm
3. dòng lệnh trong doạn mã mà hàm trở về (number line function return ) hay trong nhiều sách còn viết là địa chỉ mà hàm đó thực hiện (the address at which the function is executing)
vấn đề 1: Chính vì stack frame chứa 3 thông tin trên nên trong 2 đoạn mã địa chỉ của x và y cách xa nhau đến vậy.
vấn đề 2: Do trong code 2 có 3 stack chứ không phải 2 stack như trong code 1 nên khoảng cách địa chỉ giữa 2 đoạn mã là khác nhau.
Không biết thế đã đúng chưa . Mong mọi người vào ủng hộ
|
|
|
|
|
[Question] Re: Thảo luận về địa chỉ vùng nhớ Stack |
08/01/2008 07:13:38 (+0700) | #2 | 108971 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Tớ nghĩ đúng như thế. Bản thân 1 hàm có thể được lưu trữ tại những vị trí khác nhau trong bộ nhớ (stack frame theo bạn nói), vị trí này phụ thuộc vào cách load chương trình vào bộ nhớ để thực thi. Theo tớ nghĩ, nó đã được tạo ra vào thời điểm chạy chương trình chứ không phải khi bắt đầu gọi hàm, và tồn tại mãi cùng chương trình nếu không có gì đặc biệt. Trong vùng nhớ của hàm có thể chứa các biến cục bộ của nó, nên địa chỉ của các biến này phụ thuộc vào địa chỉ của hàm. Do vị trí các hàm là khác nhau nên địa chỉ các biến cũng khác nhau.
Bạn cũng có thể kiểm tra điều này bằng cách sử dụng 1 con trỏ hàm, rồi in thử ra giá trị của nó (tức là địa chỉ của hàm).
Nói thêm 1 chút về việc truyền tham số trong hàm, tớ nghĩ không nhất thiết chúng được lưu trữ trong bản thân của vùng nhớ hàm. Chúng có thể được lưu trữ trong stack (không phải stack frame). Stack thường chứa các thông tin sau khi gọi hàm:
- địa chỉ trở về, là địa chỉ của lệnh đã gọi hàm
- giá trị các tham số hoặc địa chỉ của chúng
khi hàm con được thực hiện xong, nó (hoặc hàm mẹ) có nhiệm vụ giải phóng các tham số trong stack và trả lại điều khiển cho hàm mẹ thông qua địa chỉ trở về đó. |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Thảo luận về địa chỉ vùng nhớ Stack |
08/01/2008 13:01:58 (+0700) | #3 | 109025 |
TQN
Elite Member
|
0 |
|
|
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
|
|
Do kích thước của của các đoạn code prolog, SEH, stack check... của các compiler # nhau.
Sinh mã ASM tương ứng với các compiler mà cậu đang dùng để check, sẽ thấy ngay, và sẽ hiểu "à, bây giờ em mới hiểu tại sao giun chết".
Hiểu cái này phải gọi là nhờ vào Reverse Engineering đấy. Hiểu tại sao compiler, linker, Win OS làm việc như vậy. Giỏi code chưa đủ đâu, cố gắng mò sâu hơn chút nữa.
Với các compiler hiện đại bây giờ, ngoài 3 cái: push function parameters, return address, local vars, còn 1 đống cái khác trên stack mà compiler sinh ra nữa. Đã vậy, mỗi ver của compiler sinh code cho stack # nhau nữa. Nhức cái đầu.
|
|
|
|
|
[Question] Re: Thảo luận về địa chỉ vùng nhớ Stack |
08/01/2008 14:21:22 (+0700) | #4 | 109045 |
Reversing...
Member
|
0 |
|
|
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
|
|
Vậy cho tớ hỏi là làm thế nào để biết được tham số truyền vào cho hàm nằm trong stack mà không phải là một nơi khác? Nếu lập trình assembler bản thân người lập trình có thể gọi stack ra để truyền tham số cho hàm, còn với các ngôn ngữ khác thì sao? |
|
|
|
|
[Question] Re: Thảo luận về địa chỉ vùng nhớ Stack |
08/01/2008 23:37:17 (+0700) | #5 | 109083 |
TQN
Elite Member
|
0 |
|
|
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
|
|
Tìm tài liệu về compiler cậu đang dùng, quy ước gọi: Calling Convention để đọc. VD: tìm hiểu các kiểu gọi: cdecl, pascal, stdcall, fastcall, thiscall, ....
Tất cả các ngôn ngử lập trình và compiler mà sinh mã native code đều truyền tham số hàm qua stack và các thanh ghi, không còn nơi nào khác.
VD: cdecl và stdcall: push các tham số vào stack từ phải qua.
fastcall trong Delphi dùng EAX, ECX, EDX để truyền 3 tham số đầu tiên, các tham số còn lại push từ phải qua.
pascal call trong Pascal cũ push tham số từ trái qua. |
|
|
|
|
[Question] Re: Thảo luận về địa chỉ vùng nhớ Stack |
09/01/2008 04:54:11 (+0700) | #6 | 109154 |
|
zThienLongz
Member
|
0 |
|
|
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
|
|
Cho em hỏi ngoài 3 cái trên complier còn sinh thêm những cái gì ạ, anh có thể vd cho em vài cái đc không
thanks |
|
|
|
|
[Question] Re: Thảo luận về địa chỉ vùng nhớ Stack |
16/01/2008 03:32:42 (+0700) | #7 | 110461 |
mfeng2
Member
|
0 |
|
|
Joined: 15/01/2008 12:53:58
Messages: 2
Offline
|
|
Như anh TQN có đề cập, 3 loại thông tin chính được lưu trong stack:
- Tham số truyền cho hàm: số lượng tham số, kiểu gọi hàm (tùy thuộc trình biên dịch). Tham khảo về các loại calling convention http://blogs.msdn.com/oldnewthing/archive/2004/01/08/48616.aspx. hoặc ở http://www.angelcode.com/dev/callconv/callconv.html
- Địa chỉ trả về của hàm: là địa chỉ của lệnh ngay sau lệnh call của assembly
- Biến cục bộ được sử dụng bên trong hàm: chú ý, biến này không bao gồm biến static.
Ngoài 3 thông tin chính trên, stack còn chứa nhiều thông tin khác:
- Cấu trúc SEH (Structure Exception Handling): thông tin này dùng để bắt các SEH event chain(chú ý là SEH của Windows khác với SEH của C++).
- Canary: Đây là một giá trị chèn vào stack nhằm chống khai thác stack overflow. Vấn đề về stack overflow protection sẽ bàn ở chủ đề khác.
(Có thể còn một số thông tin khác, nhờ mọi người bổ sung)
Cùng một đoạn code, khi biên dịch ở các compiler khác nhau, khi thực thi sẽ in ra địa chỉ stack khác nhau, bởi mỗi compiler có một kiểu code prolog, code epilog quản lý stack khác nhau. .
Trong Windows, mỗi thread có một stack khác nhau. Mọi hàm trong thread đều sử dụng chung stack này. Kích thước mặc định của stack này là 1MB và có thể thay đổi được khi biên dịch với tùy chọn hợp lý. Vị trí bộ nhớ chứa stack của thread và vị trí bộ nhớ chứa code thực thi của hàm hoàn toàn ở hai vùng cách biệt nhau. |
|
|
|
|
[Programming] Thảo luận về địa chỉ vùng nhớ Stack |
30/10/2012 06:13:56 (+0700) | #8 | 270576 |
ndp1007
Member
|
0 |
|
|
Joined: 19/12/2007 13:12:30
Messages: 4
Offline
|
|
Máy anh cho em hỏi xí
Đi test công ty em fail câu này, từ nào giờ không để ý máy vụ này
Sau đây là 1 Class, với Class đó, cách khai báo hàm main như thế chiếm bao nhiêu byte dữ liệu và số byte đó khác với số byte của cái file .exe khi biên dịch ?
Code:
class Student
{
int StudentID = 0;
}
void main(){
Student *a = new Student();
}
Với lại việc đặt tên Class và Attribute với nhiều kí tự hoặc ít kí tự (như Student thay = a) như vậy khi biên dịch có ảnh hưởng gì tới ô nhớ hay chỉ tăng dung lượng file Code thôi ?
Mong các anh giúp đỡ
|
|
|
[Programming] Thảo luận về địa chỉ vùng nhớ Stack |
30/10/2012 07:03:45 (+0700) | #9 | 270577 |
TQN
Elite Member
|
0 |
|
|
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
|
|
Vậy đáp án đúng là như thế nào ? Chắc chắn cũng sai luôn.
Câu hỏi trên trả lời no cũng được mà yes cũng xong ? Ông nào ra câu hỏi này chắc chắn cũng không nắm rõ về compiler sinh mã C/C++ ra sao, compiler nào, option compile/link như thế nào nữa.
|
|
|
|