2012-02-12 12 views
5

In C++ quando faccio new (o anche malloc) c'è qualche garanzia che l'indirizzo di ritorno sarà maggiore di un certo valore? Perché ... in questo progetto trovo molto utile usare 0-1k come enum. Ma non vorrei farlo se è possibile ottenere un valore così basso. I miei unici sistemi di destinazione sono CPU a 32 o 64 bit con la finestra OS/Linux e Mac.Il puntatore è garantito per> un certo valore?

Lo standard dice qualcosa sui puntatori? Windows o Linux dicono qualcosa sul loro runtime C e quale è l'indirizzo di memoria più basso (per ram)?

-edit- finisco per modificare il mio sovraccarico new per verificare se l'indirizzo è superiore a> 1k. Io chiamo std :: termina se non lo fa.

+1

Perché stai usando le enumerazioni come indicatori? – Pubby

+1

@Pubby: è comune (in particolare negli interpreti e nei giochi) affidarsi a caratteristiche del puntatore specifiche della piattaforma per inserire ulteriori informazioni in esse, di solito per eliminare l'indirezione.A causa delle regole di allineamento, i tre bit inferiori sono liberi; inoltre, i sistemi a 64 bit hanno generalmente puntatori userspace con solo 48 bit significativi; il resto sono tutti '1' o' 0', quindi puoi impacchettare un puntatore nella mantissa (53-bit) di un 'double' con i suoi bit superiori impostati per rappresentare' NaN'. Quindi i flag di ordine basso ti consentono di scegliere rapidamente tra le rappresentazioni con mascheramento e spostamento. –

+0

Sembra che mi bastino solo 6 bit, quindi non ho nemmeno bisogno del primo 1 o 4k :). –

risposta

4

Non esiste alcuna garanzia. Puoi provare a utilizzare placement new se hai bisogno di posizioni di memoria molto specifiche ma ha alcuni problemi che dovrai fare con work hard to avoid. Perché non provi a utilizzare una mappa con una chiave intera che ha invece il puntatore come valore? In questo modo non dovrai fare affidamento su specifici indirizzi e intervalli di memoria.

2

In teoria, nessun puntatore non è nemmeno garantito che sia> 0. Tuttavia, in pratica, visualizzato come un numero intero senza segno (non dimenticare che un puntatore può avere un bit "1" di ordine elevato), nessun sistema che conosca avrebbe un valore di puntatore inferiore a circa 1000. Ma fare affidamento su questo si basa su "comportamento non definito".

+1

riferimento? Penso di ricordare che il primo 1GB nella memoria virtuale di linux è solo per il kernel, [quindi se è vero, l'applicazione non riceverà un indirizzo nel primo 1GB, a meno che non funzioni sulla modalità kernel] Tuttavia, potrei essere sbagliato riguardo l'ipotesi iniziale, non riesco a ricordare dove penso di averlo letto: \ – amit

+0

@amit il mio google-fu ha inventato questo http://linux-mm.org/HighMemory "3GB per i programmi utente e 1GB per il kernel" –

+0

@amit - Stavo parlando in generale - il C++ gira su alcuni sistemi piuttosto piccoli. –

1

Non esiste uno standard per l'origine di indirizzi di memoria validi; per scrivere codice sicuro indipendente dal sistema, non è possibile fare affidamento su determinati indirizzi (e anche con il supporto aneddot, non si sa mai quando cambierà con un nuovo aggiornamento di sistema).

6

In termini di standard, non c'è nulla. Ma in realtà, dipende dal SO di destinazione, Windows per esempio riserva i primi 64kb di memoria come una terra di nessuno (a seconda della build è una memoria di sola lettura, altrimenti è contrassegnata come PAGE_NOACCESS), mentre usa il 0x80000000 + superiore per la memoria del kernel, ma può essere modificato, vedere this & this su MSDN.

Su x64 è possibile utilizzare anche i bit più alti dell'indirizzo (solo 47 bit sono attualmente utilizzati per gli indirizzi), ma non è una buona idea, poiché in seguito cambierà e il programma si interromperà (AMD che imposta il lo standard lo sconsiglia anche).

+0

buona risposta +1. –

1

'molto specifica piattaforma, quindi vorrei scoraggiare fare affidamento su questo tipo di informazioni a meno che non si dispone di una buona ragione e sono a conoscenza di conseguenze per la portabilità, la manutenibilità ecc

NULL è garantito per essere 0x0 sempre. Se ricordo correttamente, x86 riserva i primi 128 MB di spazio degli indirizzi come "NULL-equivalent", in modo che i puntatori validi non possano assumere valori in questo intervallo. Su x64 ci sono alcuni additional addresses che non dovresti incontrare nella pratica, almeno per ora.

Come per lo spazio indirizzo riservato al sistema operativo, dipenderà chiaramente dal sistema operativo. Su Linux, la divisione dello spazio utente del kernel è configurabile nel kernel, quindi almeno le 3 divisioni: 1-3 GB, 2-2 GB e 3-1 GB sono comuni nei sistemi a 32 bit. Puoi trovare maggiori dettagli on kerneltrap.

+0

Sicuramente intendevi il primo 128 * K * B di spazio indirizzo? –

+0

@CodyGray No, in realtà è 128 MB, non kB. Ma non ero del tutto corretto riguardo alle cause. Non è causato dalla CPU stessa, ma piuttosto dal layout dello spazio degli indirizzi delle applicazioni sulla maggior parte dei sistemi simili a UNIX. L'area 0-128 MB è riservata allo stack, il che significa che non si ottengono gli indirizzi da questo intervallo quando si utilizza 'new' o' malloc() 'che allocano memoria dall'heap. È spiegato molto bene in [questa bella risposta] (http://stackoverflow.com/a/2187753/1224016). –

Problemi correlati