2013-02-21 9 views
6

Czy to możliwe, aby uzyskać pozostałą ilość dostępnej pamięci w systemie (x86, x64, PowerPC/Windows, Linux lub MacOS) w standardowy C++ 11 bez awarii?Uzyskaj pozostałą dostępną pamięć w standardowym C++ 11?

naiwny sposób byłoby spróbować przydzielania bardzo duże tablice zaczynające się od zbyt dużych rozmiarów, złapać wyjątki każdym razem to się nie powiedzie i zmniejszyć rozmiar, dopóki nie jest wyjątek. Ale może jest bardziej efektywna/sprytna metoda ...

EDYCJA 1: W rzeczywistości nie potrzebuję dokładnej ilości pamięci. Chciałbym wiedzieć w przybliżeniu (pasek błędu 100 MB), ile mój kod mógłby użyć, gdy go uruchomię.

EDIT 2: Co sądzisz o tym kodzie? Czy bezpieczne jest uruchamianie go na początku mojego programu lub może to spowodować uszkodzenie pamięci?

#include <iostream> 
#include <array> 
#include <list> 
#include <initializer_list> 
#include <stdexcept> 

int main(int argc, char* argv[]) 
{ 
    static const long long int megabyte = 1024*1024; 
    std::array<char, megabyte> content({{'a'}}); 
    std::list<decltype(content)> list1; 
    std::list<decltype(content)> list2; 
    const long long int n1 = list1.max_size(); 
    const long long int n2 = list2.max_size(); 
    long long int i1 = 0; 
    long long int i2 = 0; 
    long long int result = 0; 
    for (i1 = 0; i1 < n1; ++i1) { 
     try { 
      list1.push_back(content); 
     } 
     catch (const std::exception&) { 
      break; 
     } 
    } 
    for (i2 = 0; i2 < n2; ++i2) { 
     try { 
      list2.push_back(content); 
     } 
     catch (const std::exception&) { 
      break; 
     } 
    } 
    list1.clear(); 
    list2.clear(); 
    result = (i1+i2)*sizeof(content); 
    std::cout<<"Memory available for program execution = "<<result/megabyte<<" MB"<<std::endl; 
    return 0; 
} 
+0

Niestety, tym razem wyszło "nie" z dwóch możliwych wyników "może". –

+0

To zależy od platformy i nie jest obsługiwane w standardzie. –

+0

Nie ma "standardowego" sposobu, aby to zrobić. Nawet opisana metoda może nie zwrócić prawidłowych wyników. Musisz użyć funkcji specyficznej dla platformy. –

Odpowiedz

8

Jest to wysoce zależne od systemu operacyjnego/platformy. Podejście, które sugerujesz, nie musi nawet działać w prawdziwym życiu. W niektórych platformach OS udzieli Ci wszystkich żądań pamięci, ale naprawdę nie daje pamięć aż użyć to, w którym momencie pojawi się wysypać ...

Norma ma nie ma nic związanego do tego.

+0

Segfault nie byłby prawdopodobnym rezultatem. W systemie Mac OS X proces zostałby zawieszony. W każdym razie, maszyna zwykle zaczynała "thrashować" jako pierwsza. – Potatoswatter

+0

@Potatoswatter: Wypróbuj pole linuxowe, usuń plik wymiany, przydziel wystarczająco dużą tablicę dynamiczną i przejdź przez nią dotykając wszystkich, powiedzmy 4096. bajtów, aby dotknąć wszystkich stron pamięci. Przynajmniej w przeszłości ostatecznie zginie z SEGFAULT –

+0

@ DavidRodríguez-dribeas - To jest Linux, OSX jest inny. To jest "wysoce zależne", jak powiedziałeś. Kluczową kwestią jest to, że w niektórych systemach można z powodzeniem przydzielić znacznie więcej pamięci, niż jest to możliwe nawet w pamięci wirtualnej, gdzie "sukces" oznacza brak rzutu z nowego lub wskaźnik o wartości innej niż zero z malloc. Problem może nie pojawić się długo po tym, jak fałszywa ilość pamięci została "pomyślnie" przydzielona. –

2

Wydaje mi się, że odpowiedź jest nie, nie można tego zrobić w standardowej C++.

Co można zrobić zamiast tego jest omówione pod How to get available memory C++/g++? i treści tam połączonych. To wszystko zależy od platformy. Nie jest to standard, ale przynajmniej pomaga rozwiązać problem, z którym masz do czynienia.

1

Jak wspomnieli inni, problem jest trudny do precyzyjnego zdefiniowania, a tym bardziej rozwiązania. Czy pamięć wirtualna na dysku twardym jest liczona jako "dostępna"? Co się stanie, jeśli system wdroży monit o usunięcie plików, aby uzyskać więcej miejsca na dysku twardym, tymczasem zawieszając swój program? (To jest dokładnie to, co dzieje się na OS X.)

System prawdopodobnie implementuje hierarchię pamięci, która pracuje wolniej, jak użyć więcej. Można spróbować wykrywania urwiska wydajności między RAM i dysku poprzez przydzielanie i inicjowanie fragmentów pamięci podczas korzystania z obiektu C alarm przerwać lub clock lub localtime/mktime lub C++ 11 zakładów z budzikiem. Czas na ścianie powinien wydawać się szybszy, gdy maszyna zwalnia w warunkach stresu związanego z uzyskaniem pamięci z mniej wydajnych zasobów. (Ale to powoduje, że nie jest on akcentowany przez nic innego, jak na przykład inny proces.) Użytkownik powinien powiedzieć użytkownikowi, co program próbuje, i zapisać wyniki w edytowalnym pliku konfiguracyjnym.

1

Zamiast tego radzę użyć konfigurowalnej maksymalnej ilości pamięci. Ponieważ niektóre platformy nadmiernie wykorzystują pamięć, nie jest łatwo powiedzieć, ile pamięci faktycznie będzie można uzyskać. Nie jest również uprzejmy zakładać, że masz wyłączny dostęp do 100% dostępnej pamięci, wiele systemów będzie działać z innymi programami.