Segmentacja pamięci i kolejność pól klasy

0

Ostatnio rozszerzałem jeden program w Qt w Windows z MinGW32, w jednej klasie, której obiekt jest tworzony na stosie (deklaracja zmiennej obiektu bez gwiazdki) dodałem kilka tablic statycznych o wielkości kilkadziesiąt kilobajtów, teraz trudno mi powiedzieć, ile pamięci jest przeznaczone na zmienne i tablice na stosie (deklaracja bez gwiazdki), ale to będzie rząd od kilkudziesięciu do kilkuset Kb.

Program kompiluję jako Release, ostatnio, jak dodałem jedną tablicę, to program w ogóle się nie uruchamiał (ale się kompilował), był błąd "SIGSEV Segmentation fault". Jak skasowałem dodatkową tablicę, to program się uruchomił. Jak zmieniłem typ tablicy z int na unsigned char (w tym przypadku wystarczył typ unsigned char), to program się uruchomił i działał poprawnie. Jak w konstruktorze tej klasy, a także w konstruktorze klasy zawierającej pole będące obiektem przedmiotowej klasy dodałem wypisanie jakiegoś napisu za pomocą cout, to nic się nie wypisało, jakby błąd wystąpił jeszcze przed zbudowaniem obiektu nadrzędnego (przed uruchomieniem konstruktora). Co może być przyczyną i z czego wynika ograniczenie wielkości struktur na stosie? Akurat z opcją Debug nie testowałem, ale spróbuje, może pokaże coś więcej.

Kiedy indziej, miałem taki przypadek, że poprawność działania programu zależała od kolejności podania pól i deklaracji metod w pliku nagłówkowym. Problem pojawiał się czasem, jak dopisałem nowe pole lub nową metodę (program się kompilował i uruchamiał, ale zaraz na początku się wywalał lub wywalał się po uruchomieniu jakiejś funkcji), ale jak przemieściłem na koniec, to problem nie występował. Jedyna przyczyna, jaka mi przychodzi do głowy, to próba zapisania lub odczytu elementu którejś tablicy ponad jej wielkość i wtedy w pamięci operacyjnej występuje treść innego pola lub zapis kodu metody i próba odczytu bądź zapisu powoduje problem. Czy jest możliwa też inna przyczyna tego problemu?

Program teraz działa poprawnie. Czy jest możliwe i na ile prawdopodobne, że pierwszy problem wróci w sytuacji, gdy będę chciał skompilować program na system inny niż Windows (jeszcze tego nie testowałem, bo nie potrzebuję i nie mam dostępu do Linuxa ani OSX)?

0

z czego wynika ograniczenie wielkości struktur na stosie?

Z wielkości stosu. W takich przypadkach używaj std::vector

0
kq napisał(a):

z czego wynika ograniczenie wielkości struktur na stosie?

Z wielkości stosu. W takich przypadkach używaj std::vector

Znam sens i działanie std::vector i rozumiem, że on na stosie umieści wskaźnik na tablicę, wielkość tablicy i inne dane o niej, a sama tablica będzie na stercie. Czyli to jest tak, jakbym zadeklarował wskaźnik na tablicę z gwiazdką i do tego kontrolował wielkość tablicy, zapewnił przepisanie do większej lub mniejszej itp, co w vector jest już zapewnione. Czy dobrze rozumiem?

Z czego wynika wielkość stosu? Czy to jest kwestia parametrów kompilacji, czy właściwość danego systemu operacyjnego i tego się nie przeskoczy?

0

@Vector tak jest, tylko pozwala na stosowanie rule of zero, co gorąco polecam.

Jeśli chodzi o wielkość stosu, to wedle tego co rozumiem możesz w parametrach linkera podać żądaną wielkość stosu: link. O ile mnie pamięć nie myli, na linuksie możesz kontrolować wielkość stosu za pomocą ulimit, ale tutaj fajnie by było gdyby ktoś zweryfikował moje słowa.

0

Wielkość stosu jest ograniczona przez system operacyjny ponieważ podczas tworzenia wątku/procesu jest z góry ustalany rozmiar stosu na którym będzie operować wątek.
Są różne sposoby wpłynięcia na jego wielkość. Istotne jest zrozumienie, że biblioteki systemowe oraz ABI dostarczają odpowiednią funkcjonalność do tworzenia wątków i procesów. Niektóre z tych funkcji biorą skonfigurowany w systemie rozmiar stosu, inne pozwalają na dostarczenie własnego obszaru pamięci, który posłuży za stos.

Istnieje jeszcze coś takiego jak "Segmented Stack" (https://releases.llvm.org/3.0/docs/SegmentedStacks.html), czyli stos, który naprawdę rośnie, a nie jest ograniczony z góry. Wiem, że język Go wykorzystuje właśnie "Segmented Stack". Wymaga to jednak dodatkowej odpowiedzialności po stronie środowiska wykonania (maszyny wirtualnej, bibliotek).

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