| |
@@ -51,3 +51,85 @@
|
| |
is required to check if propagating the attribute is
|
| |
appropriate. Incorrectly applied attributes can result in
|
| |
undesired behavioral changes in the compiled code.
|
| |
+
|
| |
+ [[sect-Defensive_Coding-C-Common-Mistakes]]
|
| |
+ === Common mistakes
|
| |
+
|
| |
+ ==== Mistakes in macros
|
| |
+ A macro is a name given to a block of C statements as a pre-processor
|
| |
+ directive. Being a pre-processor the block of code is transformed by
|
| |
+ the compiler before being compiled.
|
| |
+
|
| |
+ A macro starts with the preprocessor directive, #define. It can
|
| |
+ define a single value or any 'substitution', syntactically valid or
|
| |
+ not.
|
| |
+
|
| |
+ A common mistake when working with macros is that programmers treat
|
| |
+ arguments to macros like they would functions. This becomes an issue
|
| |
+ when the argument may be expanded multiple times in a macro.
|
| |
+
|
| |
+ For example:
|
| |
+
|
| |
+ macro-misuse.c
|
| |
+ [source,C]
|
| |
+ ----
|
| |
+ #define simple(thing) do { \
|
| |
+ if (thing < 1) { \
|
| |
+ y = thing; \
|
| |
+ } \
|
| |
+ else if (thing > 100) { \
|
| |
+ y = thing * 2 + thing; \
|
| |
+ } \
|
| |
+ else { \
|
| |
+ y = 200; \
|
| |
+ } \
|
| |
+ } while (0)
|
| |
+
|
| |
+ int main(void) {
|
| |
+ int x = 200;
|
| |
+ int y = 0;
|
| |
+ simple(x++);
|
| |
+
|
| |
+ return 0;
|
| |
+ }
|
| |
+ ----
|
| |
+
|
| |
+ Each pass through the simple() macro would mean that x could be
|
| |
+ expanded in-place each time 'thing' was mentioned.
|
| |
+
|
| |
+ The 'main' function would be processed and expanded as follows:
|
| |
+
|
| |
+ macro-misuse-post-processing.c
|
| |
+ [source,C]
|
| |
+ ----
|
| |
+
|
| |
+ int main(void) {
|
| |
+ int x = 200;
|
| |
+ int y = 0;
|
| |
+ do {
|
| |
+ if ( x++ < 1) {
|
| |
+ y = x++;
|
| |
+ }
|
| |
+ else if (thing > 100) {
|
| |
+ y = x++ * 2 + x++;
|
| |
+ }
|
| |
+ else {
|
| |
+ x = 200;
|
| |
+ }
|
| |
+ } while (0)
|
| |
+
|
| |
+ return 0;
|
| |
+ }
|
| |
+ ----
|
| |
+
|
| |
+ Each evaluation of the argument to 'simple' (x++) would be executed
|
| |
+ each time it was referenced.
|
| |
+
|
| |
+ While this may be 'expected' behaviour by the original creator, large
|
| |
+ projects may have programmers who were unaware of how the macro may
|
| |
+ expand and this may introduce unexpected behaviour, especially if the
|
| |
+ value is later used as indexing into an array or able to be
|
| |
+ overflowed.
|
| |
+
|
| |
+
|
| |
+
|
| |
First pull ive done for this project, let me know if it should be in another location. This outlines the possible misuse of macros and the automated expansion by the c pre-processor.