L'OS s'occupera de ceci. Pour le voir en action, vous devrez instrument ou appliquer débogueur au code du noyau du système d'exploitation, mais le concept peut être vu par:
int *p = new int[1000000];
Cela affectera environ 4 Mo (1000 pages) de mémoire, mais jusqu'à présent aucun d'entre eux ont été utilisés, alors rien ne sera « physiquement affecté » (mais peut-être le premier a en fait, car il est susceptible d'être utilisée pour stocker les métadonnées pour l'attribution)
p[2048] = 42;
maintenant, le système d'exploitation prendre une erreur de page pour 8192 octets dans l'allocation, et une fois que cela est terminé, la valeur 42 peut être écrite sur cette page.
L'exécution de GDB ne le montrera pas. En plus du fait qu'il est beaucoup plus lent que d'écrire sur une page physique déjà "validée", vous pouvez l'essayer en écrivant à un élément tous les 4K dans 100MB de données, ou les 250000 premières entrées dans les mêmes 100MB - puis en écrivant une deuxième fois. Les deux seront plus rapides la deuxième fois, mais grâce aux erreurs de page qui ne se produisent pas la deuxième fois, la deuxième fois dans le premier cas sera nettement plus rapide.
Un exemple:
#include <iostream>
#include <chrono>
#include <functional>
#include <memory>
void measure(const std::string& test, std::function<void()> function)
{
auto start_time = std::chrono::high_resolution_clock::now();
function();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - start_time);
std::cout<<test<<" "<<static_cast<double>(duration.count()) * 0.000001<<" ms"<<std::endl;
}
const int NWRITES = 1024*1024;
const int PAGESTEP = 1024;
const int NINTS = NWRITES*PAGESTEP; /* 1024M * sizeof(int) = 4GB */
int main()
{
std::unique_ptr<int[]> p(new int [NINTS]);
measure("Every int", [&p](){ for(int i = 0; i < NWRITES; i++) p[i] = i; });
measure("Every 4KB", [&p](){ for(int i = 0; i < NWRITES; i++) p[i*PAGESTEP] = i; });
measure("Every int", [&p](){ for(int i = 0; i < NWRITES; i++) p[i] = i; });
measure("Every 4KB", [&p](){ for(int i = 0; i < NWRITES; i++) p[i*PAGESTEP] = i; });
}
donne quelque chose comme ceci:
Every int 10.3651 ms
Every 4KB 1856.2 ms
Every int 2.4179 ms
Every 4KB 84.1603 ms
_ ** Je me demande quand une telle allocation a lieu. ** _ Dans un appel de système d'exploitation. –
Vous devez uniquement référencer la mémoire qui a été allouée par votre programme, soit dans le cadre d'un stockage statique ou automatique, soit à la suite d'un appel de fonction d'allocation dynamique. –