banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thảo luận hệ điều hành Windows Thảo luận về địa chỉ vùng nhớ Stack  XML
  [Programming]   Thảo luận về địa chỉ vùng nhớ Stack 07/01/2008 18:55:09 (+0700) | #1 | 108880
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
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ộ
[Up] [Print Copy]
  [Question]   Re: Thảo luận về địa chỉ vùng nhớ Stack 08/01/2008 07:13:38 (+0700) | #2 | 108971
[Avatar]
learn2hack
Elite Member

[Minus]    0    [Plus]
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
[Profile] [PM] [WWW]
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
[Up] [Print Copy]
  [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

[Minus]    0    [Plus]
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
[Profile] [PM] [WWW] [Yahoo!]
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.
[Up] [Print Copy]
  [Question]   Re: Thảo luận về địa chỉ vùng nhớ Stack 08/01/2008 14:21:22 (+0700) | #4 | 109045
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
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?
[Up] [Print Copy]
  [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

[Minus]    0    [Plus]
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
[Profile] [PM] [WWW] [Yahoo!]
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.
[Up] [Print Copy]
  [Question]   Re: Thảo luận về địa chỉ vùng nhớ Stack 09/01/2008 04:54:11 (+0700) | #6 | 109154
[Avatar]
zThienLongz
Member

[Minus]    0    [Plus]
Joined: 29/08/2006 10:09:05
Messages: 104
Location: World
Offline
[Profile] [PM] [WWW]
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
[Up] [Print Copy]
  [Question]   Re: Thảo luận về địa chỉ vùng nhớ Stack 16/01/2008 03:32:42 (+0700) | #7 | 110461
mfeng2
Member

[Minus]    0    [Plus]
Joined: 15/01/2008 12:53:58
Messages: 2
Offline
[Profile] [PM]
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) smilie

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. smilie.

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.
[Up] [Print Copy]
  [Programming]   Thảo luận về địa chỉ vùng nhớ Stack 30/10/2012 06:13:56 (+0700) | #8 | 270576
ndp1007
Member

[Minus]    0    [Plus]
Joined: 19/12/2007 13:12:30
Messages: 4
Offline
[Profile] [PM]
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 đỡ smilie
[Up] [Print Copy]
  [Programming]   Thảo luận về địa chỉ vùng nhớ Stack 30/10/2012 07:03:45 (+0700) | #9 | 270577
TQN
Elite Member

[Minus]    0    [Plus]
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
[Profile] [PM] [WWW] [Yahoo!]
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.
[Up] [Print Copy]
  [Programming]   Thảo luận về địa chỉ vùng nhớ Stack 30/10/2012 07:18:02 (+0700) | #10 | 270579
Stanley_00
Member

[Minus]    0    [Plus]
Joined: 01/03/2011 06:21:38
Messages: 74
Offline
[Profile] [PM]

ndp1007 wrote:
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 đỡ smilie
 


Sao bạn không tự thử nghiệm luôn đi nhỉ? Có thể dùng sizeof để kiểm tra kích thước của class đó.
[Up] [Print Copy]
  [Programming]   Thảo luận về địa chỉ vùng nhớ Stack 01/11/2012 07:46:22 (+0700) | #11 | 270643
ndp1007
Member

[Minus]    0    [Plus]
Joined: 19/12/2007 13:12:30
Messages: 4
Offline
[Profile] [PM]
Em nghĩ, hình như đây là câu trả lời mở, có nhiều option để trả lời, giống như anh TQN nói.
Điểm ghi được tuỳ theo mức độ trả lời của ứng viên.
Em có tìm hiểu thêm là cái đó hình như phải dựa trên platform nào 32bit, hay 64bit thì phải.

Stanley_00 wrote:

Sao bạn không tự thử nghiệm luôn đi nhỉ? Có thể dùng sizeof để kiểm tra kích thước của class đó. 

Dùng tool VS 2010 bỏ qua complier header nội dung như sau :
Code:
#include <stdio.h>
#include <conio.h>
class Student
{
	private :
		int StudentID;
		char* StudentName;
	public :
		Student()
		{
			this->StudentID=0;
			this->StudentName="ndp1007";
		}
};

int main()
{
	Student *a = new Student();
	printf("%d",sizeof(a));
	getch();
	return 0;
}

Trên winxp 32bit :
Màn hình để số 4 ( dù // đi 2 attribute StudentID và Name, thay int = float, char ... cũng là số 4) (1)
Size của file exe là 32 Kb ( k0 biết máy compiler của máy Editor khác ntn )

(1) : Cái này em cũng ko rõ, huynh nào giải thích dùm em với smilie

Em hiểu là size của 1 lớp là = sum(Attributes of Class)
Khi khai báo Student *a = new Student(); thì con trỏ a trỏ tới địa chỉ được cấp phát với size = size của class Student ?

Mà giữa 2 cách khai báo Student *a vs Student *a = new Student() size chiếm trong bô nhớ có khác nhau không ? ( Theo như em test code trên thì như nhau)
[Up] [Print Copy]
  [Programming]   Thảo luận về địa chỉ vùng nhớ Stack 01/11/2012 10:31:40 (+0700) | #12 | 270648
vd_
Member

[Minus]    0    [Plus]
Joined: 06/03/2010 03:05:09
Messages: 124
Offline
[Profile] [PM]
thở dài...

a là pointer => size = 4

sizeof(a) là size của a => 4
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 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|