C preprocessor

From OSDev.wiki
Jump to navigation Jump to search
This page is a stub.
You can help the wiki by accurately adding more contents to it.

C preprocessor

The C preprocessor is a powerful tool and properly used may be very useful. The following have been checked to work in GCC.

Rules

This page is a stub.
You can help the wiki by accurately adding more contents to it.

Uses

#define MAX(a,b)   ((a) > (b) ? (a) : (b))

This definition has the impact of computing one of a,b twice so the sideeffects would happen twice.

#define MAX(a,b)  ({typeof(a) _a = (a); \
                    typeof(b) _b = (b); \
                    _a > _b ? _a : _b;})

Using GCC statement expressions and typeof we may avoid this problem.


This page is a stub.
You can help the wiki by accurately adding more contents to it.

Uses for debugging

Assertions are used to catch situations which should never happen, even under error circumstances.

#define assert(condition) do { if (!(condition)) { complain("assertion fail: " #condition); panic(); } } while(0)
assert( sizeof(struct free_memory_block) == 8 );
assert( 1 != 2 );
assert( gdt_ptr != null );

Assertions may be turned off in production code

#define assert(x) do {} while(0)

Some rare unrecoverable errors should be tested for also in production code and these test should not be disabled so that we recognise the problem instead of having random crashes

#define testif(condition) do { if (!(condition)) { complain("testif fail: " #condition); panic(); } } while(0)
testif( isChecksumCorrect( kernel_heap.first_free_list ) );
testif( timersAreOn );

Capturing debugging information like values of variables at different moments of execution

void alert(const char *msg);
void alert(uint32 u);
void alert_dec(uint32 u);
#define complain(msg) do {\
          alert_decimal(__FILE__); \
          alert(": "); \
          alert_decimal(__LINE__); \
          alert(": "); \
          alert(msg); \
          alert("\n"); \
      } while(0)
void * malloc(size_t s) {
  complain((uint32)kernel_heap.first_free->addr);
  do_something();
  complain((uint32)kernel_heap.first_free->addr);
  if (do_something2()) y = malloc(sizeof(struct book_keeping_struct));
  complain((uint32)kernel_heap.first_free->addr);
  do_something3();
}

with an output of

src/memory/malloc.c: 271: 0xd0010000           //entering malloc
src/memory/malloc.c: 273: 0xd0010000           //having done_something
src/memory/malloc.c: 271: 0xd0010000           //do_something2 makes malloc to recursive call
src/memory/malloc.c: 273: 0xd0010000           //done_something
src/memory/malloc.c: 275: 0x0e1bc30a           //aha! an error after do_something2() (which returns 0) in nested malloc call

...

Finding death point or program flow

SYSFAIL: page fault, %eip= 0xc0001d330, %cr2=0x00000000
#define lnDbg do { alert("<<"); alert(__func__); alert(" : "); alert_decimal(__LINE__); alert(">>\n"); } while(0)
13 void a(int i) {
14 lnDbg;
15 if (fun(i)) c(i) else a(i-1);
16 lnDbg;
17 a(i);
18}
19 void c(int i) {
20 lnDbg;
21 if (!is(i)) return ;
22 lnDbg;
23 c(i+1);
24 lnDbg;
25}
<<a: 14>>
<<c: 20>>       //line 16 wasn't run, fun(i) has returned true
<<a: 16>>       //line 22 wasn't run, !is(i) has returned true
<<a: 14>>
SYSFAIL: ....   //after line 14 neither line 20 or 16 has been reached so the call fun(i) caused the page fault.

Such macros may be stored in an shared.h file included by other compilation units.

This page is a stub.
You can help the wiki by accurately adding more contents to it.

Deleted Code

A code block may be commented out to delete it from the program, however nesting deleted fragments may reduce legibility with C++ style comments, and C comments do not nest at all. A better solution is to wrap the code in and #if 0-#endif block, where the conditional 0 means false :

#if 0
    print("memory state: ");
    print(mem->state);
    print("\nallocated blocks: ");
    print(mem->allocs);
#endif

Many editors, like VIm have by default syntax highlighting rules that treat such #if 0-#endif blocks as comments. The #if-#endif directives must be balanced, single-quotes characters must balance etc. so for deleting non-code text use comments instead.


Hazards of the C preprocessor

There is a number of counter-intuitive consequences of macros and macro expanding design. Macro Pitfalls

See also

External Links

The GNU C preprocessor manual: