2010-02-01 4 views
5

Vedo un comportamento completamente diverso quando si esegue un programma che tenta di superare RSS su macchine diverse. Il codice è qualcosa di simile:malloc si comporta in modo diverso su macchine diverse

... 
    char** s = (char**)malloc(10000*sizeof(char*)); 

    for (i = 0; i < 10000; i++){ 
    s[i] = (char*)malloc(1000*1000*sizeof(char)); 
    if (s[i] == NULL) { 
     printf("cannot allocate memory for s[%d]",i); 
     exit(1); 
    } 
    } 

    int j = 0; 
    while(1){ 
    for (i = 0; i < 10000; i++){ 
     for (j = 0; j < 1000*1000; j++) { 
     s[i][j] = 1; 
     } 
     if ((i % 100) == 0) printf("i = %d\n", i); 
    } 
    } 
    for (i = 0; i < 10000; i++) 
    free(s[i]); 
    free(s); 
... 

Il codice sopra tenta di allocare circa 10 GB di memoria utilizzando malloc. Le prime due macchine che ho provato su questo codice sono state eseguite su Linux kernel 2.6 e l'ultima su Linux kernel Linux 2.4. Ecco i comportamenti che vedo su queste macchine:

Machine1: la memoria viene allocata utilizzando overcommit di memoria, ma quando si assegnano valori alle posizioni di memoria nel ciclo while, assegna solo quanto consentito da RSS. Così OOM Killer uccide il processo quando viene stampato i = 3800, che è circa 4 GB di memoria di questa macchina.

Machine2: la memoria viene allocata utilizzando l'overcommit di memoria e il ciclo while si attiva per sempre, allocando le pagine dalla memoria virtuale. Il processo diventa un po 'più lento dopo che i = 3800 viene stampato, il che è normale.

machine3: questa macchina ha solo 2 GB di memoria. La memoria non può nemmeno essere assegnata. Sembra che l'over commit non sia impostato o che il kernel 2.4 non supporti l'allocazione delle pagine delle macchine virtuali usando malloc! Quindi nel primo ciclo for esce quando si alloca memoria per i = 2138

L'azione desiderata è quella che si verifica in machine2. Qualcuno sa quali opzioni (del kernel?) Devono essere impostate per consentire al sistema operativo di allocare pagine di memoria virtuale usando malloc e avviare il paging mentre la memoria richiesta supera l'RSS?

Grazie

+1

Dove è "if (s! = NULL)" della prima allocazione? –

+0

Preferenza personale: invece di 'char ** s = (char **) malloc (10000 * sizeof (char *));' and 's [i] = (char *) malloc (10000 * sizeof (char)); 'Vorrei fare' char ** s = malloc (10000 * sizeof * s); 'e' s [i] = malloc (10000 * sizeof ** s); '. In questo modo, se 's' cambia da un' char ** 'a un' wchar_t ** 'in futuro, tutte le chiamate di' malloc' si adatteranno se necessario. In generale, il cast del valore di ritorno 'malloc()' non è necessario in C, ed è considerato da alcuni (come me) una cattiva idea in quanto ostacola la manutenibilità. –

+0

Architettura? x86_64? –

risposta

5

Non saranno in grado di allocare 100 GB su una macchina a 32 bit e l'indirizzo usando puntatori regolari, che è ciò che il codice sembra usare. Il fatto che la macchina 1 termini il processo quando raggiunge circa 4 GB e la macchina 2 non suggerisce fortemente che la macchina 2 stia utilizzando un sistema operativo a 64 bit.

+0

Ho fatto un errore nel mio messaggio originale che ho modificato e corretto. Se si guarda il codice che richiede solo 10 GB di memoria e non 100 GB. In ogni caso, entrambe le macchine 1 e 2 eseguono sistemi operativi a 64 bit. Questi due dovrebbero essere identici poiché il loro hardware è esattamente lo stesso e configurato in modo identico. – Pirooz