| Even without array bounds checking, a bit of discipline and smart conventions will go a long way of reducing errors: 1. Define a macro function for retrieving the length of an array: #define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
2. Don't introduce macro constants for array lengths; hard code the length in the declaration and use LEN to retrieve it. Example: int a[100];
...
for (i = 0; i < LEN(a); i++) {
...
}
3. Define a macro function for dynamic array allocation: #define NEW_ARRAY(ptr, n) \
(ptr) = malloc((n) * sizeof (ptr)[0]); \
if ((ptr) == NULL) { \
fprintf(stderr, "Memory allocation failed: %s\n", strerror(errno)); \
exit(EXIT_FAILURE); \
}
4. When you create a function with an array argument, also add an argument for the array length.5. Use a convention for naming the length of array pointer targets, for instance by adding the suffix `Len'. Example: int *b, bLen = 100;
...
NEW_ARRAY(b, bLen); /* nice to know that b and bLen belong together */
...
SomeFunction(b, bLen, ...);
...
for (i = 0; i < bLen; i++) {
...
}
6. Define your own safe wrappers around unsafe standard library functions or use someone else's code that does that. |
In my experience it's most likely that a function will write past the bounds of a buffer that's been passed as an argument. In that case, make sure the size of array is always included as an argument as you said in 4.