• Chris (unregistered)

    With that last example you realise that syntax highlighting in code editors us such a blessing.

  • joe.edwards (cs)

    The first one is stupid, the second one looks like it stems from a misunderstanding of how C handles strings, and the third looks like it's a server-side script where you can just change the comment markers to change the response of the web server. Of course, it would be clearer to just put // at the beginning of two of the lines.

  • Kefer (cs) in reply to Chris

    That last one is centainly one of the most confusing ways to do commenting...

  • Rafael Larios (unregistered) in reply to joe.edwards

    I'm getting tired of reading: this is just stupid is not a WTF!!!

    Well for me the first example is a big WTF, a little more of WTFness and the example could go to college, graduate, work in finnancial institutions, marry and have children by means of copulating with female WTFs.

  • xeron (unregistered)

    I think the first one was actually attempting to make each item point to a seperate instance of "\nDEFAULT", and went about it in quite a bizarre way.

  • Coincoin (unregistered)

    /* First! /* The real WTF*//is the forum software. / I personally like those small SoD, // Where is the wooden*///table?/keep them coming. / They need FILE_NOT_FOUND Captcha: tastey */

  • Stilgar (unregistered) in reply to xeron

    if true what is the point? what is more = new String("\nDEFAULT"); would have accomplished that... I think

  • Ben Olive (cs) in reply to Coincoin
    Coincoin:
    /* First! /*

    Why do you say first when the first post was an hour before you?

  • pl (unregistered) in reply to Stilgar

    The WTF is that in polish "dupa" (as in strdupa()) means "ASS".

  • qwerty (unregistered)

    9th

  • muhahaha (unregistered) in reply to Ben Olive
    Ben Olive:
    Coincoin:
    /* First! /*

    Why do you say first when the first post was an hour before you?

    That 'First!' was commented out. Can't you read?!?

  • cheesy (cs) in reply to Chris
    strcpy( buffer, string);
    strcat( buffer, "\0");

    psh! everyone knows it should be this:

    strcpy( buffer, string);
    buffer[strlen(buffer)] = '\0';

    ignorant fools!

  • UnresolvedExternal (unregistered) in reply to cheesy
    psh! everyone knows it should be this:

    strcpy( buffer, string); buffer[strlen(buffer)] = '\0';

    ignorant fools!

    or even:

    buffer[0] ='\0'; prependString(buffer,string)

    You can take my CAPTCHA from my cold dead hands!

  • anne (unregistered) in reply to Coincoin
    Coincoin:
    /* First! /* The real WTF*//*is the forum software. */ I personally like those small SoD, /*/* Where is the wooden*//*/*table?*/keep them coming. /* They need FILE_NOT_FOUND Captcha: tastey */

    that was awesome!!! I had to paste it into my emacs window to read it!!!

    Um, I can imagine a backwards compiler that parsed that wrong, thinking it's a nested comment and like having a stack of /*. but if it happened i'd have to kill myself.

  • Gert (unregistered) in reply to cheesy

    err, the last line is ridiculous... strcpy already takes care of the ending NUL char... rtfm and in case it wouldnt, strlen() would not help as strlen also looks for the NUL char (which isnt there, its probably somewhere out of the memory allocated to that variable) and you would overwrite another NUL (pretty damn good change for access violation)

  • s (unregistered)

    strdupa...

    dupa means arse in polish.

  • Chris (unregistered) in reply to Gert
    Gert:
    err, the last line is ridiculous... strcpy already takes care of the ending NUL char... rtfm and in case it wouldnt, strlen() would not help as strlen also looks for the NUL char (which isnt there, its probably somewhere out of the memory allocated to that variable) and you would overwrite another NUL (pretty damn good change for access violation)

    Hear the "wwwoooshh" sound? That's the other posters joke going right over your head.

  • MET (cs) in reply to Gert
    Gert:
    err, the last line is ridiculous... strcpy already takes care of the ending NUL char... rtfm
    You must be new here.
  • Gert (unregistered)

    forgot to quote the comment:

    strcpy( buffer, string); buffer[strlen(buffer)] = '\0';
    my comment was for this, not the article
  • snoofle (unregistered) in reply to Chris

    using Java:

     final static Character A = new Character((char)0x42) /* letter */;
     final static Character B = new Character((char)0x41) /* letter */;
     // ...
     final static Character CR= new Character((char)0x13) /* letter */;
     
     // WTF-way to create a string
     public String makeString(Collection letters, 
                              Boolean    mode) {
       if (!mode != !!false) {
          String s = "";
          for (String theLetter : letters) {
               s += (""+theLetter);
          }
          return s.toString();
       } else if (!mode != !false) {
          String data[] = { CR,D,E,F,A,U,L,T };
          return makeString(new ArrayList(Arrays.asList(data));
       } else {
          Characterdata[] = {F,I,L,E, N,O,T, F,O,U,N,D};
          return makeString(new ArrayListArrays.asList(data));
       }
    }
    
    
  • Jon Skeet (unregistered) in reply to Gert
    Gert:
    forgot to quote the comment:
    strcpy( buffer, string); buffer[strlen(buffer)] = '\0';
    my comment was for this, not the article
    Er, yes - but it was still posted sarcastically. The poster wasn't trying to suggest it was *actually* appropriate code to use.
  • bobday (cs) in reply to joe.edwards
    joe.edwards@imaginuity.com:
    The first one is stupid, the second one looks like it stems from a misunderstanding of how C handles strings, and the third looks like it's a server-side script where you can just change the comment markers to change the response of the web server. Of course, it would be clearer to just put // at the beginning of two of the lines.
    Yes... we know.
  • snoofle (unregistered) in reply to snoofle

    Damn: gotta start proofreading before posting...

    snoofle:
    using Java:
     final static Character A = new Character((char)0x42) /* letter */;
     final static Character B = new Character((char)0x41) /* letter */;
     // ...
     final static Character CR= new Character((char)0x13) /* letter */;
     
     // WTF-way to create a string
     public String makeString(Collection letters, 
                              Boolean    mode) {
       if (!mode != !!false) {
          String s = "";
          for (String theLetter : letters) {
               s += (""+theLetter);
          }
          return s.toString();
       } else if (!mode != !false) {
          String data[] = { CR,D,E,F,A,U,L,T };
          return makeString(new ArrayList(Arrays.asList(data),!!!Boolean.TRUE);
       } else {
          Characterdata[] = {F,I,L,E, N,O,T, F,O,U,N,D};
          return makeString(new ArrayList(Arrays.asList(data),!!!Boolean.FALSE);
       }
    }
    
    
  • mlambir (cs) in reply to Gert

    yeah... he's new here

  • RON (unregistered) in reply to xeron
    xeron:
    I think the first one was actually attempting to make each item point to a seperate instance of "\nDEFAULT", and went about it in quite a bizarre way.

    It looks like VB, which is on .NET now, which means that all strings are interned. So any two references to the string "\nDEFAULT", no matter how they were constructed, will point to the same exact string objects in the string store.

  • Jon Skeet (unregistered) in reply to RON
    RON:
    xeron:
    I think the first one was actually attempting to make each item point to a seperate instance of "\nDEFAULT", and went about it in quite a bizarre way.

    It looks like VB, which is on .NET now, which means that all strings are interned. So any two references to the string "\nDEFAULT", no matter how they were constructed, will point to the same exact string objects in the string store.

    I don't believe that VB.NET interns all strings. C# certainly doesn't. For instance:

    string x = "hello"; string y = "hel"+"lo"; string tmp = "hel"; string z = tmp+"lo";

    x and y now refer to the same strings. z refers to a different string.

    Jon

  • Tweenk (cs)

    Bah. If only people used "safe" string functions, there would be no such problems:

    int safe_strcat(char *dest, size_t dest_size, const char *src)
    {
       if(strlen(src)+1 > dest_size)
          return -1;    // not enough space
       for(int i=strlen(dest); i<dest_size; ++i)
          dest[i] = src[i];   // append the string
       dest[dest_size] = '\0';   // null terminate
       return 0;    // ok
    }
    </pre>
    

    Count the WTFs! :D

  • Misha (unregistered)
    strcpy( buffer, string); strcat( buffer, "\0");

    I especially like how the coder has used double-quotes, so there are actually two null bytes. Possibly the extra one is for redundancy, in case cosmic radition flips a bit in the first one? Or maybe it's for unicode support! Genius!!!!1

  • AdT (unregistered) in reply to Jon Skeet
    Jon Skeet:
    I don't believe that VB.NET interns all strings. C# certainly doesn't.

    Neither does VB.NET (which uses largely the same libraries after all):

    Imports System.Text
    
    Module Module1
    
    	Sub Main()
    		Dim x, y As String
    		x = "foo"
    		y = "foo"
    		Console.WriteLine("{0}", Object.ReferenceEquals(x, y))
    
    		x = New String("foo")
    		y = New String("foo")
    		Console.WriteLine("{0}", Object.ReferenceEquals(x, y))
    
    		Dim sb As StringBuilder
    		sb = New StringBuilder
    		sb.Append("foo")
    		x = sb.ToString
    		y = sb.ToString
    		Console.WriteLine("{0}", Object.ReferenceEquals(x, y))
    	End Sub
    
    End Module
    

    prints

    True
    False
    False
    

    so only the string literals were interned. Sorry for the bad layout, but the WTFish forum software inserts
    elements into

    -sections. shudder

  • mrprogguy (cs)

    strfry()?

    I thought that was only for text manipulation on Chinese web sites.

  • James (unregistered)

    Strings can cut both ways. Null terminators perplex; re-write it in Perl.

  • john doe (unregistered) in reply to snoofle
    Comment held for moderation.
  • pl2 (unregistered) in reply to pl
    pl:
    The WTF is that in polish "dupa" (as in strdupa()) means "ASS".
    ... and is one of the most popular polish password elements.
  • AnthonyG (cs)

    Hehe, That's a new one. I've never seen someone try to append the already present null terminator...

  • howdy (unregistered) in reply to AnthonyG
    AnthonyG:
    Hehe, That's a new one. I've never seen someone try to append the already present null terminator...
    You're also assuming the strcpy() function supplies the null terminator. There are many libraries with improper implementations that don't supply it. General rule of thumb in *real* software development is to not trust *any* of the str* functions until the library has been properly vetted (and even then be wary) [and before someone says "use a *real* library/language/...", you must live in La-La Land where you have control over such decisions ... never leave if such is the case]. This is especially true in the embedded world. Now, using strcat to supply the null terminator, that part is bizarre.
  • savar (cs) in reply to Ben Olive
    Ben Olive:
    Coincoin:
    /* First! /*

    Why do you say first when the first post was an hour before you?

    If you read the whole thing, he's aping the WTF memes.

  • newfweiler (cs) in reply to cheesy
    cheesy:
    strcpy( buffer, string);
    strcat( buffer, "\0");

    psh! everyone knows it should be this:

    strcpy( buffer, string);
    buffer[strlen(buffer)] = '\0';

    ignorant fools!

    Talk about ignorant! You forgot to allocate the buffer!

    char * buffer = malloc(strlen(string));
    strcpy(buffer, string);
    

    And don't forget to free it when done!

    delete buffer;
    // Sometimes that doesn't work and you 
    // have to delete it the other way
    if (buffer)  // still allocated?
       delete [] buffer;  // or {} or whatever
    
  • bob the dingo (cs)

    c-strings < g-strings (and i'm not talking about music...)

  • Scottford (unregistered) in reply to newfweiler
    newfweiler:
    And don't forget to free it when done!
    delete buffer;
    // Sometimes that doesn't work and you 
    // have to delete it the other way
    if (buffer)  // still allocated?
       delete [] buffer;  // or {} or whatever
    

    Things are going to get very entertaining around here, real soon now.

  • ChadN (cs) in reply to howdy
    howdy:
    You're also assuming the strcpy() function supplies the null terminator.

    Pleeeeease be joking... strcpy() may be THE single easiest function in C to implement. You simply CANNOT work on a platform where you have to guard against it possibly not working. If you can't trust it, supply your own... period! The other str* functions are trickier, yes, but seriously; broken strcpy()? Really?

  • Crash Magnet (unregistered)

    On some early systems I did maintence on, some programmers would write:

    char buffer[16];

    for (i = 0; i < 16; i++) buffer[i] = '\0'; strcpy(buffer, "Some String");

    There would be houndreds of example of this idiom in the program.

    Crash Magnet

  • EvanED (cs) in reply to ChadN
    ChadN:
    howdy:
    You're also assuming the strcpy() function supplies the null terminator.

    Pleeeeease be joking... strcpy() may be THE single easiest function in C to implement. You simply CANNOT work on a platform where you have to guard against it possibly not working. If you can't trust it, supply your own... period! The other str* functions are trickier, yes, but seriously; broken strcpy()? Really?

    No, I think that strlen is easier.

    size_t strlen(const char* s)
    {
       if( s[0] == 0 ) return 0;
       if( s[1] == 1 ) return 1;
       if( s[2] == 2 ) return 2;
       if( s[3] == 3 ) return 3;
       if( s[4] == 4 ) return 4;
       if( s[5] == 5 ) return 5;
       if( s[6] == 6 ) return 6;
       if( s[7] == 7 ) return 7;
       if( s[8] == 8 ) return 8;
       if( s[9] == 9 ) return 9;
       if( s[10] == 10 ) return 10;
    
       return ERR_STRING_TOO_LONG;
    }
    howdy:
    AnthonyG:
    Hehe, That's a new one. I've never seen someone try to append the already present null terminator...
    You're also assuming the strcpy() function supplies the null terminator. There are many libraries with improper implementations that don't supply it. General rule of thumb in *real* software development is to not trust *any* of the str* functions until the library has been properly vetted (and even then be wary) [and before someone says "use a *real* library/language/...", you must live in La-La Land where you have control over such decisions ... never leave if such is the case]. This is especially true in the embedded world. Now, using strcat to supply the null terminator, that part is bizarre.

    Not to mention wrong anyway if strcpy doesn't append the null character.

    Addendum (2007-04-19 17:58): Yes, that strlen is wrong. I'm an idiot. "Thanks" to iMalc for pointing that out. ;-)

  • Devi (cs) in reply to Tweenk
    pl:
    The WTF is that in polish "dupa" (as in strdupa()) means "ASS".

    clbuttic :)

    Tweenk:

    int safe_strcat(char *dest, size_t dest_size, const char *src) { if(strlen(src)+1 > dest_size) return -1; // not enough space for(int i=strlen(dest); i<dest_size; ++i) dest[i] = src[i]; // append the string dest[dest_size] = '\0'; // null terminate return 0; // ok }

    Count the WTFs! :D

    6?

    • Not checking for bounds error properly in first if statement
    • Failing to return -1 if the for loop has to abort
    • Copying from in the middle of src instead of the beginning (pro-tip! - dest[i] = src[i-strlen(dest)]; // append the string) \o/
    • Buffer overrun on final character assignment
    • Final character assignment assumes the string ends at the end of the buffer
    • By the standard of strcat, shouldn't it return return dest not an error code?

    I suppose if you're being really picky you could complain about "i" being an int instead of size_t. But I have unilaterally decided that's not a wtf, because I'd probably do that do :)

  • bathe (unregistered) in reply to ChadN
    ChadN:
    howdy:
    You're also assuming the strcpy() function supplies the null terminator.

    Pleeeeease be joking... strcpy() may be THE single easiest function in C to implement. You simply CANNOT work on a platform where you have to guard against it possibly not working. If you can't trust it, supply your own... period! The other str* functions are trickier, yes, but seriously; broken strcpy()? Really?

    You must be relatively new to the art of computer programming if you believe somebody might be joking when they say there are broken implementations of strcpy. The reliability of the libraries has increased significantly in recent years and thus not necessarily be as problematic anymore. Regarding "if you can't trust it, supply your own", this is generally what happens with all str* functions anyway (seemingly more so for those working on embedded systems, where sometimes str* functions may not even exist). Unfortunately, this is also what had initially led to the proliferation of broken str* libraries.
  • Firestarter (unregistered) in reply to newfweiler
    newfweiler:
    cheesy:
    strcpy( buffer, string);
    strcat( buffer, "\0");

    psh! everyone knows it should be this:

    strcpy( buffer, string);
    buffer[strlen(buffer)] = '\0';

    ignorant fools!

    Talk about ignorant! You forgot to allocate the buffer!

    ...

    Use a real language that deals with memory [de]allocation for you!

    flame-on!

  • ChadN (cs) in reply to bathe
    bathe:
    You must be relatively new to the art of computer programming if you believe somebody might be joking when they say there are broken implementations of strcpy.

    I was actually more stunned by the implicit suggestion (based on the response to a previous post), that one deal with the possibility of broken str* functions by manually null terminating after each use. That is a vile thought! :)

    But yes, especially with "optimizations", I suppose I can imagine a broken strcpy(). But the canonical, unoptimized (arguably) K&R versions are small and easy to carry around with you, until you prove the library versions correct. Working with broken C string functions is like trying to write a story without consonants or vowels.

  • fennec (cs) in reply to Firestarter
    Firestarter:
    Use a real language that deals with memory [de]allocation for you!

    flame-on!

    Use a fake language that deals with memory [de]allocation for you!

  • Serpardum (cs)
    Luckily Ben, one of our field agents, has found a good example of when a StringBuffer is overkill. Apparently, it was too much trouble to type TextToPrint[Index]=sb.ToString().
    While Index<IndexN
        sb.Append("\nDEFAULT");
        TextToPrint[Index] = sb.ToString();
        sb.Remove(0, sb.Length);
        Index++;
    End While</pre>

    I'm not quite familiar with that language, looks like python to me, but it seems that for the first line, and first line only, it would add what was in sb before the loop, then add "\nDEFAULT" for every other line.

    It's definately obfuscated though.

    For instanct, say sb contained "Test". It would hit the while, append "\nDEFAULT" to "Test" making "Test\nDEFAULT" and add that as the first index, then until indexN add just "DEFAULT".

    Or am I seeing the code wrong? Without seeing the whole program, more specifically what was in sb before this while loop was hit, it would be hard to say.

  • SomeCoder (unregistered) in reply to Serpardum
    Serpardum:
    Luckily Ben, one of our field agents, has found a good example of when a StringBuffer is overkill. Apparently, it was too much trouble to type TextToPrint[Index]=sb.ToString().
    While Index<IndexN
        sb.Append("\nDEFAULT");
        TextToPrint[Index] = sb.ToString();
        sb.Remove(0, sb.Length);
        Index++;
    End While</pre>

    I'm not quite familiar with that language, looks like python to me, but it seems that for the first line, and first line only, it would add what was in sb before the loop, then add "\nDEFAULT" for every other line.

    It's definately obfuscated though.

    For instanct, say sb contained "Test". It would hit the while, append "\nDEFAULT" to "Test" making "Test\nDEFAULT" and add that as the first index, then until indexN add just "DEFAULT".

    Or am I seeing the code wrong? Without seeing the whole program, more specifically what was in sb before this while loop was hit, it would be hard to say.

    It's VB.NET and yeah, that's what it does. The first time through the loop could be special because sb could have something in it from before. The subsequent times through the loop it just puts "\nDEFAULT" in.

    However, the user of a StringBuilder there is definitely overkill.

  • iMalc (unregistered) in reply to EvanED
    EvanED:
    ChadN:
    howdy:
    You're also assuming the strcpy() function supplies the null terminator.

    Pleeeeease be joking... strcpy() may be THE single easiest function in C to implement. You simply CANNOT work on a platform where you have to guard against it possibly not working. If you can't trust it, supply your own... period! The other str* functions are trickier, yes, but seriously; broken strcpy()? Really?

    No, I think that strlen is easier.

    size_t strlen(const char* s)
    {
       if( s[0] == 0 ) return 0;
       if( s[1] == 1 ) return 1;
       if( s[2] == 2 ) return 2;
       if( s[3] == 3 ) return 3;
       if( s[4] == 4 ) return 4;
       if( s[5] == 5 ) return 5;
       if( s[6] == 6 ) return 6;
       if( s[7] == 7 ) return 7;
       if( s[8] == 8 ) return 8;
       if( s[9] == 9 ) return 9;
       if( s[10] == 10 ) return 10;
    
       return ERR_STRING_TOO_LONG;
    }
    howdy:
    AnthonyG:
    Hehe, That's a new one. I've never seen someone try to append the already present null terminator...
    You're also assuming the strcpy() function supplies the null terminator. There are many libraries with improper implementations that don't supply it. General rule of thumb in *real* software development is to not trust *any* of the str* functions until the library has been properly vetted (and even then be wary) [and before someone says "use a *real* library/language/...", you must live in La-La Land where you have control over such decisions ... never leave if such is the case]. This is especially true in the embedded world. Now, using strcat to supply the null terminator, that part is bizarre.

    Not to mention wrong anyway if strcpy doesn't append the null character.

    Yes I have definitely worked on a project using a compiler that had a broken strcpy! (no lies). Actually it worked in a few cases, but not when you were copying form a near pointer to a far pointer, or the other way around, despite the library having been written such that this was supposed to work. We made our strcpyNF, strcpyFN, strcpyNN, and strcpyFF and used those instead as they always worked.

    btw, your strlen is broken. I've never seen anyone use chars 1 thru 10 to terminate a string before.

Leave a comment on “Strings in Hiding”

Log In or post as a guest

Replying to comment #:

« Return to Article