Web Page - http://www.cs.tau.ac.il/~efif/courses/Software1_Summer_03
1. Overflow & underflow 1.1 #includechar chToLower[UCHAR_MAX+1]; void BuildTpLowerTable(void) { unsigned char ch; for (ch = 0; ch <= UCHAR_MAX; ch++) chToLower[ch] = ch; for (ch = 'A'; ch <= 'Z'; ++ch) chToLower[ch] = ch + 'a' - 'A'; } ch is never greater than UCHAR_MAX. The 1st loop will run for ever 1.2 void *memchr(void *pv, unsigned char ch, size_t size) { unsigned char *pch = (unsigned char *)pv; while (--size >= 0) { if (*pch == ch) return pch; pch++; } return NULL; } size is unsigned and cannot be smaller than 0. The loop will run for ever. This can be easily fixed: while (size-- > 0) 1.3 converts an integer to its ascii representation void IntToStr(int i, char *str) { char *strDigits; if (i < 0) { *str++ = '-'; i = -i; } strDigits = str; do *str++ = (i % 10) + '0'; while ((i /= 10) > 0); *str = '\0'; reverseStr(strDigits); } This code breaks for the single case in which i is equal to the smallest negative number. 2. Data conversion bugs 2.1 Octal int flight = 63; if (flight == 063) { } 2.2 How long is long char ch = 0xFF; if (ch == 0xFF) { } The result is compiler dependent. If char is signed by default, the expression is false, as ch is promoted to int 0xFFFF. char *pch; if (*pch - 0xFF) { } 2.3 mixing between '\0' and 0 3. Off-by-one bugs. while(i <= j) should be: wile (i < j) 4. NULL pointer dst = memcpy(malloc(length), src, length); 5. Using grabage memory 5.1 Free the block, but continue to reference the content while (ptr != NULL) { free(ptr); ptr = ptr->next; } 6. Using = instead of ==, & instead of && 6.1 if (ch = '\t') ExpandTab(); 6.2 if (pb != NULL) & *pb != 0xff) 7. Precedence bugs 7.1 Missing () while(c = getchar() != EOF) should be while((c = getchar()) != EOF) 7.2 word = bHigh << 8 + bLow; but the follwoing is probably ok word = bHigh << 8 | bLow; 8. Logic bugs 9. Using char to hold return value of getchar 9.1. char c; c = getchar(void); if (c == EOF) ... 9.2 int ch; char *str; ch = *str++ = getchar(); 10. Division by 0 11. Start of comment quot = number/*pdenom; 12. Dangling else 13. Preprocessor 13.1 #if UINT_MAX > 65535u ... #endif The UINT_MAX is defined in limit.h, but if you forget to include the header file, the #if directive above will quitely fail - the preprocessor will replace the undefined UINT_MAX with 0. 13.2 Evaluating macros char chGetNext(void) { return (chRemapChar(getchar())); } if chRemapChar() is a macro that evaluates its argument more than once, you get a bug char chGetNext(void) { int ch = getchar(); return (chRemapChar(ch)); } 14. Strings 14.1 char a = "A 2 line text. This is the 1st and this is the 2nd" 14.2 strcmp if (strcmp(str1,str2)) { } 15. Array indexing 16. Copying objects that overlap with memcpy() char src[64]; char * dst = &src[16]; memcpy(dst, src, 32); memmove() should be used for the ovelapping blocks 17. Wrong assumptions using 4 instead of sizeof(int) on old machines... 18. Using oprational code in assert. void getline(char * pch) { int ch; do #ifdef DEBUG assert((ch = getchar()) != EOF); #endif while ((*pch++ = ch) != '\n'); } 19. Using uninitialized variables, memory, etc. 19.1 Allocate a block and use the uninitialized content 19.2 Using unitialized local variables 20. Call realloc to expand a block, but continue to reference the content of the old block 21. Memory leak - allocate a block and "loose" it 22. Read or write beyond the boundaries of a block 23. Fail to notice error conditions 23.1 File System FILE * fp = fopen(filename, "r"); fscanf(fp, "%d", &num); 23.2 Memory unsigned char * block = malloc(length); 24. Missing break statement in switch compound statement 25. Efficiency while (expression) { A; if (f) B; else C; D; } versus if (f) while (expression) { A; B; D; } else while (expression) { A; C; D; } 26. Scope void fnc(int * pi) { int i; *pi = &i; }