#include<stdio.h> #include<stdlib.h> #include<string.h> #include <omp.h> #include <fenv.h> /* Do not remove*/ /* Benoit Leveugle, CINES - ASA*/ /* This small program try to regroup most encountered bugs in HPC related work*/ /* Use -cpp for preprocessing with gcc and nothing with icc*/ /* ############################################################################################ ## Subroutines ############################## */ #ifdef leak void function_add(void) { double *d1 = malloc(sizeof(double) * 100); // allocate an array of 100 doubles int i; for(i=0;i<100;i++) { d1[i]=d1[i]+1.0; } // forget to free the d1 memory which was allocated inside a function } #endif main() { feenableexcept(FE_DIVBYZERO| FE_INVALID|FE_OVERFLOW); #ifdef hello // hello world printf("Hello World\n"); #endif /* ############################################################################################ ## Floating point exceptions ############################## */ #ifdef divzero // divided by zero, fpe double d1,d2,d3; d2 = 10.0; d3 = 0.0; d1 = d2 / d3; printf(" %f %f %f \n",d1,d2,d3); #endif #ifdef nan // generate a nan, fpe double d1,d2; d2 = 10.0; d1 = acos(d2); printf(" %f %f \n",d1,d2); #endif #ifdef overflow // generate an overflow, same as underflow, fpe double d1,d2; d2 = 10e10; d1 = exp(d2); printf(" %f %f \n",d1,d2); #endif /* ############################################################################################ ## uninitialized ############################## */ #ifdef uninitstatic // use a non initialized value, static double d1,d2; d1 = d2*10.0; printf(" %f %f \n",d1,d2); #endif #ifdef uninitdynamic // use a non initialized value, dynamic double *d1 = malloc(sizeof(double)*10); double *d2 = malloc(sizeof(double)*10); d1[3] = d2[4]*10.0; printf(" %f %f \n",d1[3],d2[4]); free(d1); free(d2); #endif #ifdef uninitalloc // use a non initialized value, not allocated double *d1 = malloc(sizeof(double)*10); double *d2; d1[3] = d2[4]*10.0; printf(" %f %f \n",d1[3],d2[4]); free(d1); #endif /* ############################################################################################ ## allocations ############################## */ #ifdef unalloc // try do free an non allocated variable double *d1; double *d2; free(d1); #endif #ifdef allocalloc // try do allocate an already allocated variable double *d1; d1 = malloc(sizeof(double)*10); d1 = malloc(sizeof(double)*100); free(d1); #endif #ifdef nonfree // detect not freed memory double *d1 = malloc(sizeof(double)*10); double *d2 = malloc(sizeof(double)*100); int i; for(i=0;i<100;i++) { d2[i] = 100.0; } d1[3] = d2[4]*10.0; printf(" %f %f \n",d1[3],d2[4]); free(d1); #endif /* ############################################################################################ ## arrays ############################## */ #ifdef outofbound // out of array bounds, read or write double *d1 = malloc(sizeof(double)*10); int i; for(i=0;i<10;i++) { d1[i] = 10.0; } printf(" %f %f \n",d1[1],d1[10]); free(d1); #endif /* ############################################################################################ ## io ############################## */ #ifdef ionotopen char str1[10], str2[10], str3[10]; int year; FILE * fp; fp = fopen ("file.txt", "w+"); // not a good practice, prefer w and r, and play with r, r+, w, w+, a, a+, x, x+ to secure file operations if (fp == NULL) { printf("Error opening file!\n"); exit(1); } fputs("We are in 2014 \n", fp); rewind(fp); if( fscanf(fp, "%s %s %s %d", str1, str2, str3, &year) != EOF) { printf("Read String1 |%s|\n", str1 ); printf("Read String2 |%s|\n", str2 ); printf("Read String3 |%s|\n", str3 ); printf("Read Integer |%d|\n", year ); } else { printf("Could not read file"); } fclose(fp); #endif /* ############################################################################################ ## memory leak ############################## */ #ifdef leak function_add(); // the pointer 'd1' no longer exists, but the memory is still allocated. Leak. function_add(); #endif /* ############################################################################################ ## stack overflow ############################## */ #ifdef stackover double U1[1000000]; #pragma omp parallel default(none) private(U1) { U1[0]=1.0; printf("Hello World\n"); } #endif /* ############################################################################################ ## buffer overflow ############################## */ #ifdef bufferover char A[8] = {}; unsigned short B = 1979; strcpy(A, "excessive"); // 'excessiv' go to A, remaining 'e' goes to B which follows in stack memory : buffer overflow #endif printf("\nEnd\n"); }