C Code Creep



  • The C code that follows was written by a student engineer that spent a traineeship in our lab. His program was very poorly documented, and in a futile effort to find more information I even read the  traineeship report he wrote for his school, which contained about fifteen grammar and spelling errors per page (despite being written in the student's mother tongue).
    We eventually found that his program was bugged so the results we computed with it were unusable.

    The program started with this nice wtf: 

    sscanf(line_cour_route,
            "%s %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i",
            instr,&id_route, &Bp, &nb_sauts,
            &n_r[0],&n_r[1],&n_r[2],&n_r[3],&n_r[4],&n_r[5],&n_r[6],&n_r[7],&n_r[8],&n_r[9],
            &n_r[10],&n_r[11],&n_r[12],&n_r[13],&n_r[14],&n_r[15],&n_r[16],&n_r[17],&n_r[18],&n_r[19],
            &n_r[20],&n_r[21],&n_r[22],&n_r[23],&n_r[24],&n_r[25],&n_r[26],&n_r[27],&n_r[28],&n_r[29],
            &n_r[30],&n_r[31],&n_r[32],&n_r[33],&n_r[34],&n_r[35],&n_r[36],&n_r[37],&n_r[38],&n_r[39],
            &n_r[40],&n_r[41],&n_r[42],&n_r[43],&n_r[44],&n_r[45],&n_r[46],&n_r[47],&n_r[48],&n_r[49],
            &n_r[50],&n_r[51],&n_r[52],&n_r[53],&n_r[54],&n_r[55],&n_r[56],&n_r[57],&n_r[58],&n_r[59],
            &n_r[60],&n_r[61],&n_r[62],&n_r[63],&n_r[64],&n_r[65],&n_r[66],&n_r[67],&n_r[68],&n_r[69],
            &n_r[70],&n_r[71],&n_r[72],&n_r[73],&n_r[74],&n_r[75],&n_r[76],&n_r[77],&n_r[78],&n_r[79],
            &n_r[80],&n_r[81],&n_r[82],&n_r[83],&n_r[84],&n_r[85],&n_r[86],&n_r[87],&n_r[88],&n_r[89],
            &n_r[90],&n_r[91],&n_r[92],&n_r[93],&n_r[94],&n_r[95],&n_r[96],&n_r[97],&n_r[98],&n_r[99]);

     

    A few pages below there was this horror: 

             j = 0;
             while (fichier_noeud[j] != (char )NULL) {
                j++;
             }
             fichier_noeud[j] = 0x5f;
             fichier_noeud[j+1] = 0x30 + i /1000;
             fichier_noeud[j+2] = 0x30 + ( i/100 - ( (i/1000)%10 ) *10 );
             fichier_noeud[j+3] = 0x30 + ( i/10 - ( (i/100)%10 ) *10 - ( (i/1000)%10) * 100);
             fichier_noeud[j+4] = 0x30 + ( i - ( (i/10)%10 ) *10  - ( (i/100)%10 )*100 - ( (i/1000)%10)*1000 );
             fichier_noeud[j+5] = (char) NULL;
             affiche_noeud_fichier(fichier_noeud);
             fichier_noeud[j] = (char) NULL;
             i++;

    This code simply concatenates the four-digit number i to the string fichier_noeud. Now I'd like to point out three things:

    1) this whole blob could easily be replaced by  sprintf(str, "%s", i); strcat(fichier_noeud, str);

    2) even if one were ignorant about C sytem functions and too lazy to look it up on Google, it would make sense to compute the four digits only once and store them into four int variables, instead of performing about thirty mathematical operations,

    and 3) I'd like to know where this guy learnt that strings end with a null pointer instead of a NUL (backslash-zero) char.


    Dulcis in fundo, even the shell script that called the program contained a few gems:

    mkdir ../$REP_SIMUL/$FICH_RES/
    rm ../$REP_SIMUL/$FICH_RES/*

    mkdir ../$REP_SIMUL/$FICH_FIG/

    rm ../$REP_SIMUL/$FICH_FIG/*

     



  •  Gosh !

     fichier_noeud means this young student was a french one... Would you be kind enough to share with us its school of origin ?

     



  •  @D0R said:

    mkdir ../$REP_SIMUL/$FICH_FIG/
    rm ../$REP_SIMUL/$FICH_FIG/*
    When you just don't trust the system not to mess with you...



  • @Wam said:

     Gosh !

     fichier_noeud means this young student was a french one... Would you be kind enough to share with us its school of origin ?

     

     

    Sure. He studied at the Ecole d'Ingénieurs Werner-Trintignant-Foucault, better known as the Ecole WTF.  



  • @DOA said:

     @D0R said:

    mkdir ../$REP_SIMUL/$FICH_FIG/
    rm ../$REP_SIMUL/$FICH_FIG/*
    When you just don't trust the system not to mess with you...

     

    I don't get it. What if the directory already existed? You probably want to delete whatever crap was sitting there before using it.

     



  • @smxlong said:

    @DOA said:

     @D0R said:

    mkdir ../$REP_SIMUL/$FICH_FIG/
    rm ../$REP_SIMUL/$FICH_FIG/*
    When you just don't trust the system not to mess with you...

     

    I don't get it. What if the directory already existed? You probably want to delete whatever crap was sitting there before using it.

     

    Yeah, I mean, what could possibly go wrong?



  • @SpoonMeiser said:

    @smxlong said:

    I don't get it. What if the directory already existed? You probably want to delete whatever crap was sitting there before using it.

     

    Yeah, I mean, what could possibly go wrong?

     

    Lots of things could possibly go wrong, but in many cases it's rather useless to care about them. If a script is to run on millions of computers with an unknown configuration, it must be written as defensive as possible. If it runs on exactly one computer, with a known configuration, the situation is completely different. 



  • @smxlong said:

    I don't get it. What if the directory already existed?

     

     

    Exactly. But in this case mkdir fails. The non-WTF way of doing this is first to test if the directory exists. Even the solution of rm -rf the dir first is better than the original code.   



  • printf("%s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", "WTF", ...);



  • @samanddeanus said:

    printf("%s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", "WTF", NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN);

    FTFY.



  • @D0R said:

    Even the solution of rm -rf the dir first is better than the original code.   
     

    I supposed, as long and as $REP_SIMUL and $FICH_FIG are properly set, you're not running this near the root directory, and you're not running this as root to begin with.

    Scripted rm's as root with dynamically created directory/file paths always give me the willies. Even if you're absolutely sure nothing could possibly go wrong, there's always that one potential code path you hadn't considered between all's well and "uh oh, the script made the server eat itself"



  • @MarcB said:

    Scripted rm's as root with dynamically created directory/file paths always give me the willies.

    Which is why you should build the path, run it through a routine to canonize it and then check that it isn't an improper directory.  This isn't rocket science.  There is no reason to fear things like recursive file removal if you actually bother to do it correctly. 


  • Discourse touched me in a no-no place

    @derula said:

    @samanddeanus said:

    printf("%s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", "WTF", NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN);

    FTFY.

    C doesn't have a NaN constant (though one can be created at runtime,) and even if it did, it is a floating point format, not an integer format. Replace the %i with %g perhaps?



  • @D0R said:

    and 3) I'd like to know where this guy learnt that strings end with a null pointer instead of a NUL (backslash-zero) char.

     

     NULL == 0. Characters in C are just ints. '\0' == 0. NULL == '\0'. QED.



  • @D0R said:

    The program started with this nice wtf: 

    sscanf(line_cour_route,
            "%s %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i
            %i %i %i %i %i %i %i %i %i %i",
            instr,&id_route, &Bp, &nb_sauts,
            &n_r[0],&n_r[1],&n_r[2],&n_r[3],&n_r[4],&n_r[5],&n_r[6],&n_r[7],&n_r[8],&n_r[9],
            &n_r[10],&n_r[11],&n_r[12],&n_r[13],&n_r[14],&n_r[15],&n_r[16],&n_r[17],&n_r[18],&n_r[19],
            &n_r[20],&n_r[21],&n_r[22],&n_r[23],&n_r[24],&n_r[25],&n_r[26],&n_r[27],&n_r[28],&n_r[29],
            &n_r[30],&n_r[31],&n_r[32],&n_r[33],&n_r[34],&n_r[35],&n_r[36],&n_r[37],&n_r[38],&n_r[39],
            &n_r[40],&n_r[41],&n_r[42],&n_r[43],&n_r[44],&n_r[45],&n_r[46],&n_r[47],&n_r[48],&n_r[49],
            &n_r[50],&n_r[51],&n_r[52],&n_r[53],&n_r[54],&n_r[55],&n_r[56],&n_r[57],&n_r[58],&n_r[59],
            &n_r[60],&n_r[61],&n_r[62],&n_r[63],&n_r[64],&n_r[65],&n_r[66],&n_r[67],&n_r[68],&n_r[69],
            &n_r[70],&n_r[71],&n_r[72],&n_r[73],&n_r[74],&n_r[75],&n_r[76],&n_r[77],&n_r[78],&n_r[79],
            &n_r[80],&n_r[81],&n_r[82],&n_r[83],&n_r[84],&n_r[85],&n_r[86],&n_r[87],&n_r[88],&n_r[89],
            &n_r[90],&n_r[91],&n_r[92],&n_r[93],&n_r[94],&n_r[95],&n_r[96],&n_r[97],&n_r[98],&n_r[99]);

    Damn, that looks a lot like a matrix. Except uni-dimensional!



  • @devurand said:

    @D0R said:

    and 3) I'd like to know where this guy learnt that strings end with a null pointer instead of a NUL (backslash-zero) char.

     

     NULL == 0. Characters in C are just ints. '\0' == 0. NULL == '\0'. QED.

    Only when you're running that code on an 8-bit computer. ;)

    NUL == '\0' == 0x00

    NULL == 0x0000 (16-bit) or 0x00000000 (32-bit).



  • @danixdefcon5 said:

    @devurand said:

    @D0R said:

    and 3) I'd like to know where this guy learnt that strings end with a null pointer instead of a NUL (backslash-zero) char.

     

     NULL == 0. Characters in C are just ints. '\0' == 0. NULL == '\0'. QED.

    Only when you're running that code on an 8-bit computer. ;)

    NUL == '\0' == 0x00

    NULL == 0x0000 (16-bit) or 0x00000000 (32-bit).

     

    Either I missed some sarcasm, or your statement is TRWTF. On a 64 bit MacBook:

      

    ~ % cat blah.c                                               [9:57:38 08-06-12]
    #include <stdio.h> #include <stdlib.h>

    int main() {
    char* str = (char*)malloc(80*sizeof(char));
    printf("Enter a string: ");
    scanf("%s", str);
    int i;
    for(i = 0; str[i] != (char)NULL; i++)
    printf("%c\n", str[i]);
    }
    ~ % gcc blah.c [9:57:39 08-06-12]
    ~ % ./a.out [9:57:55 08-06-12]
    Enter a string: TRWTF
    T
    R
    W
    T
    F
    ~ % [9:58:07 08-06-12]


  • Discourse touched me in a no-no place

    @devurand said:

    @D0R said:

    and 3) I'd like to know where this guy learnt that strings end with a null pointer instead of a NUL (backslash-zero) char.

     

     NULL == 0. Characters in C are just ints. '\0' == 0. NULL == '\0'. QED.

    No, NULL in C is 0 in a pointer context, and in the headers is usually defined as (void*)0

    In C++ it's 0. 

    @devurand said:

    char* str = (char*)malloc(80*sizeof(char));
    What's that redundant second char* there for? You've already included <stdlib.h> Do you cast the return values from (say) scanf() into an int?



  • @PJH said:

    @devurand said:
    char* str = (char*)malloc(80sizeof(char));
    What's that redundant second char there for? You've already included <stdlib.h> Do you cast the return values from (say) scanf() into an int?
    Most likely he's used to C++ which will choke if you don't use the explicit cast since malloc returns void* not char*.


  • Discourse touched me in a no-no place

    @PJH said:

    @devurand said:
    char* str = (char*)malloc(80*sizeof(char));
    What's that redundant second char* there for?
    .. and something else I missed before the edit timeout - what is sizeof(char) doing there as well?

    (I'm ignoring the fact that <font face="courier new,courier">char str[80]</font> would have sufficed to begin with) 



  • @PJH said:

    @devurand said:

    @D0R said:

    and 3) I'd like to know where this guy learnt that strings end with a null pointer instead of a NUL (backslash-zero) char.

     

     NULL == 0. Characters in C are just ints. '\0' == 0. NULL == '\0'. QED.

    No, NULL in C is 0 in a pointer context, and in the headers is usually defined as (void*)0

    In C++ it's 0. 

    And a pointer is... nothing but a number. In the case of NULL, that number is 0.

    @PJH said:


    @devurand said:

    char* str = (char*)malloc(80*sizeof(char));
    What's that redundant second char* there for? You've already included <stdlib.h> Do you cast the return values from (say) scanf() into an int?

     

    Habit. I learnt C++ before C, and little artifacts like that tend to show up occasionally. 


  • Discourse touched me in a no-no place

    @Lingerance said:

    Most likely he's used to C++ which will choke if you don't use the explicit cast since malloc returns void* not char*.

    1) Unlikely - this is one of those 'void main()' cases where cargo-cult reigns. Authors get it wrong, their students follow. If this isn't the case then:

    2) When writing new code in C++, you really shouldn't be using malloc() (with exceptions. Toy code on messageboards are not one of them.)


  • Discourse touched me in a no-no place

    @devurand said:

    And a pointer is... nothing but a number. In the case of VOID, that number is 0.

    The point being there are different classes of numbers, and if you're looking at the lower level of C, then yes, NULL is 0. On a higher level there is a difference (however semantic you wish to make it) between NULL, NUL, 0 and 0.0.

    For example - by your argument, the following snippets are the same:

    float a = 5 / (2 + 0);

    float a = 5 / (2 + 0.0);

    After all, 0.0 is just 0. But they aren't.

     

    Another (more obscure) example:

    printf("%p\n", NULL); // correct

    int c = 0; 

    printf("%p\n", c); // wrong.



  • @PJH said:

    @devurand said:

    And a pointer is... nothing but a number. In the case of VOID, that number is 0.

    The point being there are different classes of numbers, and if you're looking at the lower level of C, then yes, NULL is 0. On a higher level there is a difference (however semantic you wish to make it) between NULL, NUL, 0 and 0.0.

    For example - by your argument, the following snippets are the same:

    float a = 5 / (2 + 0);

    float a = 5 / (2 + 0.0);

    After all, 0.0 is just 0. But they aren't.

     

    Another (more obscure) example:

    printf("%p\n", NULL); // correct

    int c = 0; 

    printf("%p\n", c); // wrong.

     

     Well, of course the first example produces integer division, which gives a different result than floating-point division. I compiled and ran the printf example, though, and it compiled/ran just fine. Granted, this isn't something you ought be doing, but beyond that was there anything else wrong with it?

     

    I think I understand more now where the argument is coming from. At first blush, I thought the OP was saying that this would not work. But now that I read over it, it looks like it was more intended to be "this is a supid way to do it." Which I agree with, though I have seen code that uses that particular idiom before.



  •  @PJH said:

    what is sizeof(char) doing there as well?

    Because, on some architectures, char is not 1 byte in size.

    @PJH said:

    What's that redundant second char* there for?

    "ANSI C defines an implicit coercion between the void pointer type and other pointer types. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in modern C code.However, omitting the cast creates an incompatibility with C++, which requires it."

    From  http://en.wikipedia.org/wiki/Malloc




  • @Spikeles said:

    "ANSI C defines an implicit coercion between the void pointer type and other pointer types. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in modern C code.However, omitting the cast creates an incompatibility with C++, which requires it."

    Using malloc() in C++ is considered bad form.  Then again, some would argue that C++ is all about bad form. 



  • @devurand said:

    I think I understand more now where the argument is coming from. At first blush, I thought the OP was saying that this would not work. But now that I read over it, it looks like it was more intended to be "this is a supid way to do it." Which I agree with, though I have seen code that uses that particular idiom before.
     

    Exactly. The code works, as well as the whole program; the bug I wrote about was in the logic, not in the syntax -- this is why it was so difficult to find. The WTF here is that the programmer seemed to believe that a NUL char and a null pointer were the same thing.  


  • Discourse touched me in a no-no place

    @Spikeles said:

     @PJH said:

    what is sizeof(char) doing there as well?

    Because, on some architectures, char is not 1 byte in size.

    Wrong. In C, sizeof(char) is defined as 1. Regardless of whether CHAR_BITS is 8 or 24, sizeof(char) is always 1.




  • @Spikeles said:

    Because, on some architectures, char is not 1 byte in size.

    That's false.

    @C99, 6.5.3.4(3) said:

    When [i][sizeof is][/i] applied to an operand that has type char, unsigned char, or signed char,
    (or a qualified version thereof) the result is 1. ~SNIP~

    @C++98, 5.3.3(1) said:

    ~SNIP~ sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; ~SNIP~



  • @PJH said:

    @Spikeles said:

     @PJH said:

    what is sizeof(char) doing there as well?

    Because, on some architectures, char is not 1 byte in size.

    Wrong. In C, sizeof(char) is defined as 1. Regardless of whether CHAR_BITS is 8 or 24, sizeof(char) is always 1.



    I could be off-base here, but I'm pretty sure this wasn't always true. I seem to remember that char, like int, was platform-dependent. I'd just about be willing to bet that sizeof(char) was fixed at 1 when wchar_t was introduced in ANSI C. (Not that I'm actually going to bother to look it up...)


  • Discourse touched me in a no-no place

    @dgvid said:

    @PJH said:

     Wrong. In C, sizeof(char) is defined as 1. Regardless of whether CHAR_BITS is 8 or 24, sizeof(char) is always 1.


    I could be off-base here, but I'm pretty sure this wasn't always true.
    It may not have true in the past, but it's been true for at least the past 18 years. See other post that quotes The Standards.



  • To be fair, "sizeof(char)" makes the purpose more clear. If you write "malloc(4 * 1)", it doesn't indicate wether you're allocating an array of 4 chars, or a single integer for a particular archetype.



  • @Faxmachinen said:

    To be fair, "sizeof(char)" makes the purpose more clear. If you write "malloc(4 * 1)", it doesn't indicate wether you're allocating an array of 4 chars, or a single integer for a particular archetype.

    Pssst..  "malloc(4)".. 


  • Discourse touched me in a no-no place

    @Faxmachinen said:

    To be fair, "sizeof(char)" makes the purpose more clear.
    It's redundant and clutters the code.

    @Faxmachinen said:

    If you write "malloc(4 * 1)", it doesn't indicate wether you're allocating an array of 4 chars, or a single integer for a particular archetype.
    What's on the left hand side of the = gives you a clue. Besides, if you're allocating for ints, you would/should use sizeof(int) in there which can change between architectures.

    (The fact that the *1 in that example is redundant has already been pointed out.)

     



  • @morbiuswilters said:

    Pssst..  "malloc(4)".. 

    Like PJH already pointed out, that's a stupid way to do it. An integer might not be 4 bytes long, especially if it's a long integer. You fail.


  • Discourse touched me in a no-no place

    @Faxmachinen said:

    Like PJH already pointed out, that's a stupid way to do it.
    Only if the intent is to allocate for an int. It's fine if you want to allocate just 4 bytes. (But then we get into the realm of using #defines or consts instead of magic numbers.)



  • Actually, I was just not very clearly making a point that neither the "malloc(4)" comment (which I believe morbiuswilters made in jest anyway), nor yours about using "sizeof(int)" are relevant, since I was only using them as an example. I think it's quite possible to make a class that has the same size across all platforms, and surely you wouldn't use "malloc(37)" rather than "malloc(sizeof(MyClass))" in that case?

     

    @PJH said:

    It's redundant and clutters the code.

    This, however, is a valid argument (as is the LHS one, by the way). But it's also quite subjective, so I'm not going to argue against it.

     



  • @Faxmachinen said:

    ...the "malloc(4)" comment (which I believe morbiuswilters made in jest anyway)...

    Not really, I was pointing out that doing 4 * 1 was pretty silly.  I don't think doing 4 * sizeof(char) is really that big of a WTF, but any competent C programmer should know that malloc(4) is allocating a 4-byte, 3-character string. 



  •  I stand corrected about the whole sizeof(char) thing. Admitedly i had never read the C or C++ specifications where this sizeof(char) is explicity defined as being 1, and it was never mentioned nor explained to me during any of my learning or training. Now that i have read the relevant parts of the spec and read other peoples views ( http://drj11.wordpress.com/2007/04/08/sizeofchar-is-1/ ) it is much clearer now. In my own personal opinon i prefer sizeof(char) anyway, since it makes it more clear, but, your coding style is your own ( or defined by company policy ), and if sizeof(char) is more understandable to you then using '1' then so be it.

     One of the reasons i like reading these forums, you learn a whole bunch of things you may never have before!



  • @morbiuswilters said:

    but any competent C programmer should know
    Oh, if only that were the one type of C programmer that exists!



  •  didn't read the thread but i would like to point out

     

    sprintf(str, "%s", i); strcat(fichier_noeud, str);

     

    contains an error (%s should be %d) be replaced by

     

    sprintf(str, "%s%d", fichier_noeud, i);



  • @Kazan said:

     didn't read the thread but i would like to point out

    sprintf(str, "%s", i); strcat(fichier_noeud, str);

    contains an error (%s should be %d) be replaced by

    sprintf(str, "%s%d", fichier_noeud, i);

     




    WTF. STOP USING sprintf and gets and other unbounded/smash-my-stack-please functions:
    It should be

    snprintf(str, sizeof(str), "%s%d", fichier_noeud, i); // assuming str is an array
    // or, even better, leaves result in the same value...
    snprintf(fichier_noeud + strlen(fichier_noeud), sizeof(fichier_noeud) - strlen(fichier_noeud),
    "%d", i);



  • I certainly hope it wasn't my school he came from (I'm also a French engineer).

    And doesn't even surprise me. My traineeship was too writing simulation stuff in raw C, but I had to work on code inherited from a previous trainee, code which was also worked on by another person doing his master thesis in the lab. First the code is handed to me as a giant .txt file which I was supposed to change to .c and put in a project; no version control. The code was basically a giant main() function (more than a thousand lines). And partway through the traineeship, I discovered a flaw in the simulation which basically meant all results obtained so far were skewed. Whee. Oh, and of course the quality of the code that was originally handed to me was about similar to that of the OP's trainee.

     

    (sorry for being late, I missed that topic when it was originally posted)


Log in to reply