Operacje na pamięci

0

Hej.
Piszę już jakiś czas w c++ i w zasadzie nigdy się nie zastanawiałem jak wygląda to co się dzieje w pamięci.
Gdy tworzę sobie zmienną operatorem new np:
new int abc();
To jest alokowana pamięć i tworzony obiekt w tym miejscu gdzieś w pamięci. Kompilator wie ile miejsca potrzebuje patrząc po typie obiektu i tyle alokuje.
Mogę zrobić taki trick że zrobię klasę z 20 polami typu int i też użyć tego operatora żeby sztucznie sobie zaalokować miejsce w pamięci(mogę to zrobić tak samo mallockiem). Operator ten zwróci mi adres na początek zajętego miejsca.
Mając to miejsce w pamięci mogę sobie już gdziekolwiek w tym obszarze chce tworzyć dowolne obiekty różnych klas i dostawać się do nich mając adres początku zajętego miejsca i offsetu stosując rzutowanie i będzie działać.
Jeżeli coś powyżej napisałem nie tak to proszę mnie poprawić.

Ja chciałem jednak sobie zapisać wartość inta w jakimś losowym miejscu pamięci. To tylko 4 bajty więc co się może stać... Chciałem stworzyć za pomocą new(losowyadres)int(5); i zaraz po tym odczytać wartość z tego miejsca. Skończyło się to crashem aplikacji. Popróbowałem kilka razy z innymi adresami i za każdym razem crash.

Teraz moje pytanie jak zachowuje się pamięć komputera. Mam Windowsa 7, 4GB ramu. Czy używając wskaźników jestem w stanie dostać się do każdej komórki tej pamięci? Dlaczego zapisanie jakiejś wartości i odczyt kończy się crashem? Czy coś blokuje programy żeby nie miały dostępu do nie zaalokowanej pamięci, jeżeli tak to jak to obejść? Te 4 bajty jeżeli należały do pamięci zarezerwowanej do jakiejś innej aplikacji to przecież jakie jest prawdopodobieństwo że akurat w tym czasie ktoś do tego obszaru coś zapisywał lub odczytywał. Czy są jakieś przedziały adresów w pamięci które są wolne i na których mógł bym zapisać wartości bez alokowania pamięci?

2
  1. Generalnie pierwsza cześć jest ok.
  2. Druga część już nie.

Czy używając wskaźników jestem w stanie dostać się do każdej komórki tej pamięci

Nie bo to nie czasy DOSa. Programy mają wirtualną przestrzeń adresową wiec twój program w normanej sytuacji nie widzi pamięci inych procesów. System operacyjny dodatkowo ma ochronę pamięci i jeśli spróbujesz odwołać się do jakiegos segmentu/adresu który nie jest w puli zaalokowanych to wysypie ci program.
https://en.wikipedia.org/wiki/Segmentation_fault

0

A jaki jest najprostsze rozwiązanie żeby obejść taką blokadę i móc zapisywać pod dowolne adresy?
Znalazłem coś takiego jak funkcje ReadProcessMemory i WriteProcessMemory. Z tego co widzę to mając handle i id aplikacji/procesu można tymi funkcjami operować na pamięci zaalokowanej przez inne procesy więc możliwość zapisu odczytu ewidentnie istnieje.

0
  1. Poczytaj o memory pool.
  2. Dlaczego chcesz pisać po nie swojej pamięci?
0

to co opisales w pierwszej czesci to jest placement new

0
satirev napisał(a):
  1. Dlaczego chcesz pisać po nie swojej pamięci?

Jak to nie mojej, kupiłem całe 4 GB to chce po niej pisać.

Tak naprawdę to chodzi mi właśnie o jakieś dobre źródło informacji. Najlepiej łopatologicznie napisane po polsku lub angielsku które mi to dokładnie wyjaśni:
To ile mój program który napiszę dostanie pamięci wirtualnej. Czy na początku jak uruchamiam program to dostaje on dokładnie tyle bajtów pamięci ile potrzeba czy może troszeczkę więcej i co jak dynamicznie alokują pamięć w trakcie działania programu jak system sobie z tym radzi.
I jak wygląda przestrzeń adresów czy jeżeli stworzę w programie powiedzmy dwie zmienne int a oraz int b.
To dlaczego ich adresy są takie duże jak by były alokowane gdzieś w środku pamięci a nie na początku. Czy to są adresy względem tej przestrzeni wirtualnej czy może rzeczywistej?
Tych pytań mi się nasuwa cała masa i chciałbym jakieś źródło gdzie to jest wyjaśnione dobrze.

0

.

0

Co do tego "jak to działa", to szukaj pod hasłami GDT. Mniej więcej to podczas bootowania system ładuje tablice GDT, i ustawia odpowiednie selektory w rejestrach segmentowych.

0

To ile mój program który napiszę dostanie pamięci wirtualnej. Czy na początku jak uruchamiam program to dostaje on dokładnie tyle bajtów pamięci ile potrzeba czy może troszeczkę więcej i co jak dynamicznie alokują pamięć w trakcie działania programu jak system sobie z tym radzi.

To zależy od systemu i używanych wersji bibliotek standardowych kompilatora.

2

Jak to nie mojej, kupiłem całe 4 GB to chce po niej pisać.
To sobie ją najpierw zaalokuj. Po to system operacyjny zarządza pamięcią i separuje procesy (programy) od siebie, by błąd w jednym programie nie uwalił innego, a za nim całego systemu. Dostęp do pamięci innych procesów jest celowo utrudniony.

To dlaczego ich adresy są takie duże jak by były alokowane gdzieś w środku pamięci a nie na początku.
Bo często są gdzieś w środku. Ponadto obecnie stosuje się address space layout randomization, czyli randomizację przestrzeni adresowej, specjalnie żeby adresy nie były od początku ani po kolei, i by za każdym uruchomieniem programu były inne. Z założenia ma to utrudniać hackowanie programów.

Czy to są adresy względem tej przestrzeni wirtualnej czy może rzeczywistej
Wirtualnej. Adresy fizyczne mogą być zupełnie dowolne (w ramach istniejącej pamięci) i mogą się zmieniać podczas pracy programu. System może przenieść stronę pamięci wirtualnej ("strona" może mieć różny rozmiar, ale powiedzmy że 4 kilobajty) z jednego miejsca pamięci fizycznej w drugie; może też ją zapisać na dysk twardy (do pliku wymiany) by zwolnić miejsce w RAM-ie. może też w szczególnych okolicznościach wyrzucić stronę tracąc jej zawartość. Dla programu są to operacje niewidoczne (przezroczyste).

1 użytkowników online, w tym zalogowanych: 0, gości: 1