Noroc,
Am primit PM despre discuția asta, așa că răspund.

Precizez de la început că nu am nicio afiliere cu OJI sau alt nivel de olimpiadă. Ca să nu încep fiecare frază cu „din câte È™tiu eu...â€, consideraÈ›i că tot ce scriu aici este din câte È™tiu eu.
OJI se corectează pe Windows. În schimb, evaluatorul IA rulează sub Linux. De aici decurge o diferență importantă. Iată întâi ce zice „man top†(boldul îmi aparține).
RES -- Resident Memory Size (KiB)
The non-swapped physical memory a task has used.
VIRT -- Virtual Memory Size (KiB)
The total amount of virtual memory used by the task. It
includes all code, data and shared libraries plus pages that
have been swapped out and pages that have been mapped but not
used.
Deci în Linux există conceptul de memorie pe care ai declarat-o, dar încă n-ai accesat-o și deci „nu se pune†la o eventuală limitare. Să considerăm următorul program:
#include <stdio.h>
#define N (100 * 1024 * 1024)
int main(void) {
unsigned char v[N];
while (1) {
}
return 0;
}
Dacă îl rulez, merge bine-mersi, iar top zice:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
23954 cata 20 0 4192 356 280 R 100.0 0.0 0:49.77 test
Pare deci că kernelul a mapat cumva doar 4 MB, iar programul folosește efectiv 356 KB. Să încercăm acum:
#include <stdio.h>
#define N (100 * 1024 * 1024)
int main(void) {
unsigned char v[N];
int i;
for (i = 0; i < N; i++) {
v[i] = 111;
}
while (1) {
}
return 0;
}
Acesta dă segfault. Pare deci că programul chiar cere acei 100 MB pe stivă, ceea ce nu se poate. În varianta a 3-a facem vectorul global:
#include <stdio.h>
#define N (100 * 1024 * 1024)
unsigned char v[N];
int main(void) {
int i;
for (i = 0; i < N; i++) {
v[i] = 111;
}
while (1) {
}
return 0;
}
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
24061 cata 20 0 106592 102788 312 R 100.0 1.3 1:22.81 test
Aici într-adevăr programul folosește 100 MB (nu știu de ce sunt 106 -- poate din cauza diferenței între 1.000 și 1.024).
În Windows, în schimb, dacă declari un vector static, chiar ți-l alocă. Bineînțeles, nu e normal să folosim Windows la olimpiadă și este regretabil că o generație întreagă de informaticieni de elită, smântâna cremei ca să zic așa, cresc dependenți de software neliber. Dar asta este situația curentă și, în timp ce milităm pentru renunțarea la Windows, lucrăm în contextul dat. Deci ești dator să știi că infoarena pregătește utilizatori adevărați, linuxiști, dar că ce merge pe IA nu va merge la OJI. Te cred că ești nemulțumit și te invit să militezi alături de noi pentru eliminarea Windows-ului din toate fazele olimpiadei (și, dacă se poate, din viețile noastre).
Acum, referitor la măsurarea memoriei. Codul infoarena este liber (mulțumim!) și poți vedea ce face
programul jrun în particular. Caută funcția
update_from_proc() și vei vedea că, într-o buclă, jrun cere de la sistem date despre câtă memorie folosește programul executat.
De ce așa? Pentru că nu este trivial altfel. Nu există o metodă bună de
sandboxing. Ce decurge de aici? Că, dacă faci verificarea în buclă prea des, vei gâtui programul și va ajunge jrun să ruleze mai mult decât programul. Dar, dacă o faci prea rar, riști să măsori incorect memoria maximă folosită, căci poți avea ghinionul să măsori de o parte și de alta a unui vârf.
Cam astea-s contribuțiile mele; evident, corectați-mă dacă aberez.