2016-01-29 14 views
8

mi piacerebbe scrivere una funzione di registrazione di basso livello che sarebbe simile:prova C se variabile è in sola lettura sezione

DO_DBG("some string", val1, val2) 

Quello che voglio fare, è quello di memorizzare il puntatore la stringa piuttosto che una copia della stringa, per motivi di prestazioni. Ciò presuppone che la stringa sia un valore letterale di sola lettura. Per evitare che le persone debbano eseguire il debug del debugger, sarebbe bello se il compilatore potesse lamentarsi se il primo parametro di DO_DBG si trovava in una sezione scrivibile di codice vs testo, ecc. Mi chiedo se esiste un meccanismo per farlo. (Sto usando gcc 4.9.1, ld 2.24).

+1

Se una variabile ** arbitraria o ** stringa letterale ** è di sola lettura? Lo standard C garantisce che i valori letterali stringa siano di sola lettura.Tuttavia, è definito dall'implementazione se stringhe uguali sono memorizzate allo stesso indirizzo. – Downvoter

+0

Sì, ma voglio che il compilatore fallisca la compilazione se qualcuno tenta di passare qualsiasi cosa tranne una stringa letterale come primo parametro della funzione. La funzione prenderebbe un parametro 'const char *' e voglio sapere se si tratta di un valore letterale ... – John

+0

Sembra che aggiri un comportamento indefinito e lo sostituisca con qualcosa di "più sicuro" come errori di compilazione del tempo. Non penso sia possibile senza modificare il compilatore/rompendo lo standard C. – Downvoter

risposta

7

Si potrebbe usare l'automatico letterale concatenazione di stringhe a vostro vantaggio:

#define DO_DBG(s, a, b) _DO_DBG("" s, a, b) 

e realizzare il tuo vero macro come _DO_DBG.

+1

Cosa succede se gli utenti registrano il valore '-10'? –

+0

@KerrekSB - quindi verrà generato l'errore di compilazione richiesto. – Amit

+0

Ha parlato di stringhe ... –

0

In alternativa è possibile utilizzare la stringa i macro costrutto:

#define DO_DBG(s, a, b) DO_DBG_INTERNAL(# s, a, b) 

e chiamare la funzione DO_DGB_INTERNAL così la gente avrebbe fatto:

DO_DBG(some string, val1, val2) 

PS, molto probabilmente una funzione variadic e macro sarebbe un buona idea qui.

+0

Il risultato della stringificazione è di nuovo una stringa costante, che verrà gestita proprio come una stringa scritta a mano dal programmatore. Questo non dovrebbe fare un briciolo di differenza. – vonbrand

+0

Se si fa: 'DO_DBG (some_charstar_var, ...)' si eviterà sicuramente il problema del valore di 'some_charstar_var' che cambia influenzando cosa DO_DBG memorizzato ... –

+0

Niente affatto. La gestione delle vararg è interamente in fase di runtime. – vonbrand

0

La funzione ottiene un puntatore all'inizio della stringa. Se il tuo sistema operativo lo consente e il compilatore lo imposta in quel modo, una stringa costante (come nel tuo esempio) potrebbe essere allocata in un'area di memoria di sola lettura. Se il compilatore è intelligente, memorizzerà una copia di una costante di stringa che appare più volte. Potrebbe anche capitare che alcune stringhe non vengano mai usate, e semplicemente non le memorizzino affatto.

Diversamente da quanto sopra, a meno che il programma non si basi su un comportamento non definito (superando la scrittura su una stringa costante), non si dovrebbe essere in grado di capire se si trova nella memoria di sola lettura o meno. Puoi confrontare gli indirizzi delle stringhe per vedere se sono solo una copia, ma è così.

In qualsiasi ragionevole implementazione C (ovvero, uno che non va fuori del suo modo solo per rovinarti), vedrai nessuna (o al massimo una piccolissima) differenza di prestazioni se la stringa viene letta -solo, lettura-scrittura, una copia o più.

Se si scrive si funzione con un parametro char *, e negozio ha detto puntatore lontano (non una copia della stringa puntata), si dovrebbe ottenere sempre la stessa stringa di nuovo (a meno che l'ambiente è davvero strano).

1

È possibile impostare un gestore SIGSEGV, e quindi provare a fare:

s[0] = s[0]; 

Se il gestore è attivato, significa che la variabile è in un segmento di sola lettura, in modo da poter salvare il puntatore . Altrimenti, puoi lamentarti (o semplicemente fare una copia della stringa).

È necessario dichiarare la stringa volatile in modo che il compilatore non ottimizzi l'assegnazione.

+0

Questo funzionerebbe per il tempo di esecuzione, ma OP sta cercando un controllo del tempo di compilazione. – dbush

+0

Ah, non lo sapevo. Ha parlato di aree di memoria di sola lettura e scrivibili, che sembra un problema di runtime. – Barmar

+0

È comunque un approccio interessante al test di sola lettura. Potrebbe essere utile in qualcos'altro in fondo alla strada. – John