Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Czym naprawde jest adres który przechowuje wskaźnik C++

Ostatnio zmodyfikowano 2014-02-04 15:42
Autor Wiadomość
CodeFun
Temat założony przez niniejszego użytkownika
Czym naprawde jest adres który przechowuje wskaźnik C++
» 2014-01-28 15:58:12
Witam

Chciałbym się dowiedzieć czym naprawdę jest adres który zawiera wskaźnik. Czyli
C/C++
int a;
int * b;
b = & a;

Na początku jak ja to rozumie.
Przeanalizowałem dosyć gęsto architekturę x86 i tryb chroniony, bo chyba w tym trybie pracują systemy takie jak Win XP, 7 , 8. Doszedłem do wniosku, że jest to offset w adresie logicznym, czyli adres jaki widzi sam dla siebie program. Offset ten jest jest offsetem segmentu danych (bo mówimy o zmiennej) i teraz w którym miejscu w pamięci się znajduje segment jest zawarte w deskryptorze segmentu danych.
W trybie rzeczywistym zdobywając adres danej zmiennej dostawaliśmy również offset segmentu danych, różnica polegała na tym, że rejestr segmentowy CS wtedy zawierał faktyczny adres fizyczny początku bloku segmentu danych. W trybie chronionym w rejestrze CS dostajemy SELEKTOR SEGMENTU, ten z kolei ma informacje gdzie w tablicy deskryptorów jest DESKRYPTOR SEGMENTU DANYCH a ten z kolei ma już konkretne informacje pod jakim adresem fizycznym (RAM) znajduje się nasz segment. Wtedy adres sgmentu + offset = adres fizyczny zmiennej. Normalnie baba w babie.
Aha...przy okazji. Czy mógłbym mi ktoś wytłumaczyć jak to jest możliwe, że w trybie chronionym każdy segment może mieć 4Gb ? Gdzieś to parę razy wyczytałem, ale nie załapałem tego.


P-103418
DejaVu
» 2014-01-28 16:07:53
Wyobraź sobie pamięć komputera jako jedną wielką jednowymiarową tablicę. Adres to nic innego jak numerek indeksu tej wielkiej jednowymiarowej tablicy od której zaczynają się Twoje dane. Czyli: jeżeli adres wynosi 0x33112200, to dane umieszczone są w tej wielkiej tablicy od podanego numeru 'indeksu'. Ten numerek nie mówi ile bajtów danych należy do Ciebie. Jednak skoro wiesz, że wskaźnik wskazuje na dane typu int, to skompilowana aplikacja wie, że ma odczytać 4 kolejne bajty (przy założeniu, że to achitektura 32-bitowa) poczynając od wskazanego adresu pamięci.
P-103425
CodeFun
Temat założony przez niniejszego użytkownika
» 2014-01-28 16:47:59
DejaVu

Adres to nic innego jak numerek indeksu tej wielkiej jednowymiarowej tablicy


No to nie jest chyba takie proste. Zgodzę się, że całą pamięć L1,L2+RAM+DYSK można by ująć w formie 0x0 do 0xFFFFFF...., ale tutaj chodzi o architekturę i układ MMU zarządzający pamięcią. Zgodzę się, że ta zmienna a ma swój JEDYNY UNIKALNY adres w całej pamięci fizycznej PC, ale moim zdaniem wskaźnik nie zawiera adresu fizycznego ,a offset. Gdzieś w kuble leży mój apokaliptyczny temat w którym sam sobie udowodniłem, że dwa identyczne programy uruchomione równolegle nadają tym zmiennym TEN SAM adres. Znaczy to tyle samo, że muszą mieć inny adres fizyczny. Czyli program musi mieć inny selektor dalej deskryptor i segment, a że programy są takie same zajmują tyle samo to zmienna znajduje się w tym samym miejscu WZGLĘDEM programu a konkretnie względem początkowego adresu segmentu danych.

C/C++
main()
{
    int a = 2;
    int * b;
    b = & a;
    cout << "adres zmiennej " << & a;
    cout << "adres w wskaźniku " << b;
}

Uruchom to x2 i zobacz co pokaże.
P-103429
kubawal
» 2014-01-28 17:53:32
No to chyba sam sobie odpowiedziałeś... :)
W dodatku po co ci dostęp do adresu poza pamięcią programu?
Potrzebujesz czegoś w rodzaju IPC? (jak tak, to przetestuj Boost.Interprocess)
P-103436
DejaVu
» 2014-01-28 18:14:39
Poczytaj sobie o adresowaniu pamięci w assemblerze 16-bitowym. Tam masz ładnie wytłumaczone pojęcia segmentu i offsetu oraz dlaczego ten sam adres pamięci może być wskazywany przez różne wartości. W skrócie:
adres pamięci = x*16 + y;
x <= jeden rejestr 16-bitowy (segment);
y <= drugi rejestr 16-bitowy (offset);

jak nie trudno zauważyć 1*16+0 da to samo co 0*16+16; czyli adres 0000:0010 da to samo co adres 0001:0000. Powyższy mechanizm w aplikacjach 16-bitowych umożliwiał zaadresowanie 1MB pamięci RAM. Architektura 32-bitowa oraz 64-bitowa wygląda nieco inaczej, ale... przykład powinien być dla Ciebie wystarczający do tego, aby zgłębiać kolejne tajniki adresowania pamięci.

PS. Nie wiem jaką masz ideę dalszego wgłębiania się w adresowanie pamięci, ale na poziomie wytwarzania aplikacji w języku C++ niekoniecznie powinno Ciebie to interesować jak została pamięć przydzielona aplikacji i jaki ma adres.
P-103440
CodeFun
Temat założony przez niniejszego użytkownika
» 2014-01-28 18:59:20
Ja wiem jak wygląda adresowanie w systemie 16 bitowym. Wiem jak się liczy adres rzeczywisty w trybie rzeczywistym, ale chciałem się dowiedzieć jak się liczy adres rzeczywisty w trybie chronionym, a jak się go liczy to chyba sobie sam odpowiedziałem :)
CS zawiera selektor, w selektorze jest wskaźnik na tablice deskryptorów a w deskryptorze mamy w końcu adres segmentu do adresu segmentu dodajemy offset (adres ze wskaźnika z C++) i włola mamy adres fizyczny.

A po co mi to ? Bo jestem ciekawski i lubię wiedzieć co się dzieje w systemie jak tworzę program. Taka wiedza pozwala dużo lepiej poruszać się po funkcjach systemowych, i "poczuć" co się dzieje. Kluczem jest jak zawsze architektura procesora.

Jednak nadal umyka mi jedna rzecz, segmenty. Segmenty w trybie chronionym tzn ich wielkość, jaka może być ? piszą że do 4Gb. W trybie rzeczywistym segment nie mógł mieć więcej niż 2^16, procesor nie mógł z racji magistrali 20 bitowej zaadresować więcej jak 2^20. Tutaj jest inaczej dochodzi jakaś granulacja.

http://pl.wikibooks.org/wiki/Asembler_x86/Zaawansowana_architektura

czytam to wszystko, ale chyba jak na mnie coś za mało wytłumaczone. Rozumiem, że flaga G to jakby mnożnik limitu. No i co się dzieje jak w komputerze mamy tylko 4Gb Ramu a mamy np zdeklarowane segmenty zajmujące łącznie 8 Gb, wtedy tryb wirtualny i to co mniej potrzebne jest na dysku ?
P-103447
Elaine
» 2014-01-28 19:27:38
Zapomij o segmentacji, mainstreamowe systemy operacyjne z niej nie korzystają (poza rejestrami FS i GS). To jest efekt stronicowania.
P-103459
CodeFun
Temat założony przez niniejszego użytkownika
» 2014-01-28 20:54:10
Więc zmienna "a" przy włączonym stronicowaniu znajduje się pod konkretnym przesunięciem (to to co zawiera zmienna wskaźnikowa?) w konkretnej stronie, która się znajduje w konkretnym katalogu stron ?
W takim razie co zawiera rejestr CS ? adres początku danej strony ?
P-103472
« 1 » 2
  Strona 1 z 2 Następna strona