2010-02-15 14 views
6

Il titolo quasi dice tutto, ma io vi riformulare la domanda ...Il seguente programma è un programma C99 rigorosamente conforme?

è il seguente programma un "programma strettamente conforme" sotto lo standard C99?

#include <stdlib.h> 
/* Removing any pre-existing macro definition, in case one should exist in the implementation. 
* Seems to be allowed under 7.1.3 para 3, as malloc does not begin with _X where X is any capital letter. 
* And 7.1.4 para 1 explicitly permits #undef of such macros. 
*/ 
#ifdef malloc  
#undef malloc  
#endif    

/* Macro substitution has no impact on the external name malloc 
* which remains accessible, e.g., via "(malloc)(s)". Such use of 
* macro substitution seems enabled by 7.1.4 para 1, but not specifically 
* mentioned otherwise. 
*/ 
void * journalling_malloc(size_t size); 
#define malloc(s)  ((journalling_malloc)(s))  

int main(void) 
{ 
    return malloc(10) == NULL ? 1 : 0;  
    /* Just for the sake of expanding the 
    * macro one time, return as exit code 
    * whether the allocation was performed. 
    */ 
} 
+0

BTW, sono consapevole che uno vorrebbe anche "wrap" free(), realloc(), strdup(), calloc() e who-knows-what-else. Questa non è la domanda. Una nota a margine: chissà cos'altro? Queste sono tutte le API malloc() che posso evocare dalla mia testa. –

+2

Voglio solo ricordare che questo metodo non aiuta l'uso di malloc in nessuna libreria esterna. Diverse persone forniscono implementazioni malloc alternative che possono essere aggiunte al momento del collegamento, ad esempio google all'indirizzo http://code.google.com/p/google-perftools/wiki/GooglePerformanceTools – gnud

risposta

11

Diamo un'occhiata a ciò che la norma C99 ha da dire in proposito:

vedi 7.1.3, § 1, comma 5:

Ogni identificativo con ambito file elencato in una qualsiasi delle i seguenti sottopunti [...] sono riservati per l'uso come nome macro e come identificatore con ambito file nello stesso spazio nome se uno qualsiasi degli intestazioni associate è incluso.

Come si include stdlib.h, il nome malloc è riservato per l'uso come un nome di macro.

Ma 7.1.4, § 1 permette di usare #undef su nomi riservati:

L'uso di #undef di cancellare qualunque definizione di macro garantirà inoltre che un funzione reale è denominato.

Ciò rende possibile ri- #definemalloc, che si traduce in un comportamento indefinito secondo 7.1.3, §2:

Se il programma [...] definisce un identificatore riservato come nome macro, , il comportamento non è definito.

Perché lo standard stabilisce questa restrizione? Poiché altre funzioni della libreria standard possono essere implementate come macro simili a funzioni in termini di funzione originale, nascondere la dichiarazione potrebbe interrompere queste altre funzioni.

In pratica, si dovrebbe andare bene a patto che la tua definizione di malloc soddisfa tutte le disposizioni della norma prevede la funzione di libreria, che può essere raggiunto avvolgendo una chiamata reale per malloc().

+0

Buona capacità di lettura! Se non ti dispiace, posso chiedere se puoi trovare la stessa risposta per C89 e aumentare la tua risposta qui? Se lo farai, cambierò il titolo di questa domanda. Tale renderebbe una risorsa migliore. Sta a te. –

+0

@Heath: la sezione 4.1.2 della bozza ANSI non è molto dettagliata, ma dice che "Tutti gli identificatori esterni dichiarati in una qualsiasi delle intestazioni sono riservati, indipendentemente dal fatto che l'intestazione associata sia inclusa."; la nota 87 indica essenzialmente la stessa semantica di C99 per questo caso d'uso – Christoph

+2

btw: puoi rendere il programma conforme escludendo 'stdlib.h' e dichiarando' malloc() 'tu stesso, che è esplicitamente consentito da 7.1.4 §2 – Christoph

3

Hai voglia di cambiare journalling_malloc(...)void-void *, modificare i commenti per // (perché sono commentando il vostro undef) e aggiungere un #endif vicino alla parte superiore, ma per il resto tutto sembra a posto.

+0

Buona cattura, grazie. Avevo pensato che fosse qualcosa che si sarebbe compilato, e ho fatto il cambiamento che hai suggerito. ;) –

+3

Devo aggiungere che non è necessario avvolgere #undef in modo condizionale. Va bene per #undef qualcosa che non è definito. – DigitalRoss

+0

oh uomo grazie per essere il mio compilatore umano. :) –

1

Funzionerà: Sì.

E 'conforme: No.

Secondo il C standard:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

Tutti i nomi nella libreria standard sono riservati (compreso malloc).

7.1.3 Reserved identifiers 
Specifically: 
    <quote>Each macro name in any of the following subclauses</quote> 
    <quote>All identifiers with external linkage in any of the 
    following subclauses</quote> 

anche un programma strettamente conforme volontà non può definire i nomi che sono riservati per l'attuazione (vale a dire Questo include i nomi e idnetifiers riservati, quelli per le biblioteche in corso e quelli riservati per usi futuri).

7.1.3 (note 2) 
Specifically: 
    <quote>If the program declares or defines an identifier in a context in which 
    it is reserved or defines a reserved identifier as a macro name, 
    the behavior is undefined.</quote> 

Così per definizione: definendo malloc() è non conforme perché è un comportamento indefinito (illegale).

+0

Ciò significa che si direbbe che, in base al C99, i nomi macro fanno parte dello spazio dei nomi "identificatore ordinario" definito nella sezione 6.2.3, paragrafo 1, quarto elemento del punto elenco? Chiedo perché sembra che tu stia dicendo che i nomi di macro sono in conflitto con gli identificatori ordinari. –

0

Gli identificatori di macro sono nomi propri e a tutti gli identificatori di libreria di qualsiasi tipo è vietato l'aliasing di una macro indipendentemente dallo stato linguistico delle macro.

§6.10.3/7

L'identificatore che segue immediatamente la definire è chiamato il nome della macro. C'è uno spazio dei nomi per i nomi delle macro .

§7.1.3/1

Ogni identificativo con ambito di file elencati in uno dei seguenti sottoclausole (compreso il futuro biblioteca direzioni) è riservato per l'uso come un nome di macro e come identificatore con ambito di file nello stesso spazio dei nomi se uno dei suoi intestazioni associate è incluso.

§7.1.3/2

Se il programma dichiara o definisce un identificatore in un contesto in cui è riservato (diverso da quello consentito dal 7.1.4), o definisce un identificatore riservato come nome macro, il comportamento non è definito.

+0

Sei d'accordo 7.1.3/3 specifica che uno sarebbe permesso a #undef malloc? In tal caso, stai dicendo che la lingua di 7.1.3/1 renderebbe comunque non conforme qualsiasi #define malloc indipendentemente da #undef? Inoltre, hai visto che i nomi di macro non possono essere "identificatori con scope" perché 6.2.1/1 rilascia una dichiarazione specifica sullo stato linguistico delle macro. (6.2.1 è la sezione "scope of identifier", dove "scope file" è definito per identificatori non-macro-name.) –

+0

@Heath: 7.1.3/3 proibisce solo le cose ("comportamento non definito") e si riferisce solo a tutti gli identificatori che iniziano con underscore, che 'malloc' (almeno) non è. È irrilevante che le macro non siano identificatori con scope di file; 7.1.3/1 ** riserva identificatori con ambito file ** (incluso 'malloc') ** per macro **. – Potatoswatter

+0

Ma #define non dichiara un identificatore con scope di file, perché non dichiara un identificatore. Dovresti incorporare 7.1.3/2 nella tua risposta come la prima volta che l'hai pubblicata qui e questa è la vera risposta. In particolare, come ho letto C89/C90, questa è una discrepanza rispetto allo standard precedente. C99 menziona specificamente l'uso di #define mentre C89/C90 menziona solo la dichiarazione di un identificatore esterno, che non è un nome di macro. Ad ogni modo, menziona 7.1.3/2 come hai fatto nel tuo commento eliminato e accetterò la tua risposta come corretta. È 7.1.3/2 che lo rende così. Vedo un'altra risposta, it1st –

Problemi correlati