• (cs) in reply to Dazed
    Anonymous:
    And given that there are several thousand merchants - who is volunteering to type in the configuration file? Never mind the implementation - the design is already a WTF.

    <font face="tahoma,arial,helvetica,sans-serif">And what if merchant # 9999 became a special merchant? That poor volunteer would have to fill in 9975 bytes of useless Ns before finally adding the significant one.

    Volunteer: 8756...
    Volunteer: 8757...
    Volunteer: 8758...
    Annoying guy: 8769! 8774! 7858! 7859!
    Volunteer: Shut up! I'm trying to work here... (gosh, man, grow up...)
    Volunteer: ...
    Volunteer: Darn! Where am I again?



    </font>
  • Friedrich Dominicus (unregistered)

    I know quite some other such legends. The may be legion in the "C" world ;-)

     

    However this is another really good one (tm)

     Regards

    Friedrich
     

  • no name (unregistered) in reply to xrT

    xrT:
    Anonymous:
    And given that there are several thousand merchants - who is volunteering to type in the configuration file? Never mind the implementation - the design is already a WTF.

    <font face="tahoma,arial,helvetica,sans-serif">And what if merchant # 9999 became a special merchant? That poor volunteer would have to fill in 9975 bytes of useless Ns before finally adding the significant one.

    Volunteer: 8756...
    Volunteer: 8757...
    Volunteer: 8758...
    Annoying guy: 8769! 8774! 7858! 7859!
    Volunteer: Shut up! I'm trying to work here... (gosh, man, grow up...)
    Volunteer: ...
    Volunteer: Darn! Where am I again?



    </font>

     

    Well, If he does it by hand, he deserves whatever ribbing he gets. 

  • PoP (unregistered)

    Did I read "process incoming credit card transaction files from several thousand different national merchants" or I am just not fully awake? Pleaaaaaaaaaase give us the list of the concerned merchants! :-D

     

  • (cs) in reply to PoP
    Anonymous:

    Did I read "process incoming credit card transaction files from several thousand different national merchants" or I am just not fully awake? Pleaaaaaaaaaase give us the list of the concerned merchants! :-D

     

    And which ones are special?

  • ajk (unregistered)
    Alex Papadimoulis:
    int is_special_merchant(int merchnum) 
    {
    size_t fln;
    char filedat[10000];
    FILE *file;
    int ab = 0;

    if ((file=fopen("spcmerch.cfg","r" )) == NULL ) return(1);
    fln = fread(&filedat, 10000, 1, file);

    if(fln == (size_t)0) return(1);
    fclose(file);
    if(filedat[merchnum] == 'Y') return(0);

    return(1);
    }

    And for completeness, here is the spcmerch.cfg file in its entirety. All twenty three bytes.

    NNNNYNNNYNNYYNYYNNNNYNN

     

    LOL

    Its nice to c-code in a wtf, finally something an old-timer can understand :) 

    captcha null LOL! 
  • anonymous (unregistered) in reply to nop

    Anonymous:
    The config file would te impossible to maintain. Imagine that only merchant 3049 is "special". That means the file's author has to type 3049 (remember to count from zero) N's and then a Y. And since the file is text based and used by this monstrosity I very much doubt that there's a tool to do this for you.

    Nah. You can create a custom C tool to fill to manage that or to generate from database

    $ setmerchantspecial 322 Y spcmerch.cfg
    $ setmerchantspecial 321 N spcmerch.cfg

    or

    $ regenspmerchant -db postgress://localhost:/mechants -o spcmerch.cfg

    He use 8 bits to store 1 bit, but that is handy because can be edited by hand for debugging purposes.
     

  • flash (unregistered)

    Nothing special will happen : on modern OSes your C code sees a virtual address space of 4GB anyway, so it does not matter if you have only 1GB or 512 megs of physical memory. OTOH, if you are close to the 4GB border in 32bits mode, address calculation will wrap around.

  • Anonymous coward (unregistered) in reply to Anonymous
    <quote> 
     6.  Any merchantnum > 10000 will just simply core dump/IPF depending on operation system.

    or simply get garbage (i.e., see #3)

    </quote>

     It is claimed that merchant numbers are 4 digits (i.e. 0000 to 9999). Last time I checked 9999 < 10000 :-)

     

     

  • Coditor (unregistered) in reply to themagni

    themagni:
    As someone else said, "It's like your VCR manual: it doesn't say what happens if you insert a banana upside down in zero gravity. It's undefined."

    I never heard that expression before, but it's brilliant! :D (allthough I'm not sure that there is such a thing as up or down in zero gravity...)

    Can someone please explain why a company has everyone coding in one language, and only 1 guy programming in his own language? I would love to work for that company and go back to writing in Basic ;)

    Coditor

    Today's question: Java is OOP, C is OOP, so together are they OOPS?

  • (cs) in reply to Coditor

    Well we are close to that....

    I bought 4 rechargable batteries for my MP3 player.. And it came with an USB Charger for one batterie...

     What really made me sad is the label on the charger... Right on the Cap under which the USB Connector is you can read

     "Remove before use"

    It just made me sod... 

  • KoFFiE (unregistered) in reply to nop
    Anonymous:
    • The file is opened, read, and closed for *each* record being processed.


    That is not a WTF at all... On any decent system this is blazingly fast. For quick peeking at a file this is actually good practice, so you don't have too many files open or forget to close a few...

    I think the wtf's are more summed up by:

    • He allocates 10k on stack, which is quite a lot. Ok, on modern machines/os'es this is no problem but still... For any buffer above 1k, I consider using malloc as the saner option.
    • No boundry checks, reading random memory when merchnum > file length
    • true/false inverted
    • Not closing the file when it's an empty file
    • Reading in the whole fucking file. Guess seek(fp, merchnum, file) and then reading 1 byte was too hard...
    • Unmaintainable. I hope the other merchant data is stored in the database? Or do they have files like this too for that? *grin*
    • what's "int ab = 0;" doing there? Not used as far as I can see
    • Path of the file? Just look in current directory and hope you're ok?
    • Example won't even compile *grin* - the "if ((file=fopen("spcmerch.cfg","r" )) == NULL ) return(1);" line has 1 ) too much :)
    But well, I could imagine a few ways to make it a bigger wtf (but without the bugs). Use a bit-array for example, then you only need 1250 bytes instead of 10000 for 10000 merchants... :D
  • (cs)
    Anonymous:

    Obviously my question is not easily understood.  Your explainations are to the idea that there si still memory locations to access, and yes that is understood.  But what if we have filled our physical memory almost completly. 

    You have 1 gig worth of memory, you fill all but 10k of it, you then create an array that fills 9k.  You attempt to access a location 9.5k past the end, no problem, buffer overrun. 

    But try to access something 11k past the end.  Herin lies my question.  Since there is no physical address what happens?  A pure core dump?  A wrap to the beginning for system memory (which I doubt)? Or something else?  This is totally undefined behaviour based off my knowledge. 

    Remember C tends to believe that the programmer knows what he is doing and will attempt it regardless of the ramifications.  Some other languages (vb) notice this access and simply raises an out of bounds error.

    Unlikely to happen. Realistically, you take the virtual address of the array start, add n to it, convert it to a physical address, and perform the memory access. It doesn't matter what the physical addresses are on a modern OS, since you never see them. It doesn't really matter what the virtual address is, because 0xFFFFFFFF + 1 == 0 (on a 32-bit OS).

    The behaviour is undefined since you don't know what that area of memory actually is. If it's not in your page tables, you get a page fault. If it in your page tables, you may also get a page fault depending on access permissions.

    Now, if you're actually using physical addresses, either the memory access succeeds (returning garbage if it's physically unmapped, or performing I/O if it's a device, or just reading a random area of memory if it's mapped to memory), or it fails because you tried to access RAM that didn't exist.
     

  • anonymous (unregistered) in reply to Coditor

    Anonymous:
    Today's question: Java is OOP, C is OOP, so together are they OOPS?

    Well. Is not lenguajes that are OOP, but is style that is oop alike. But a lang can be "oop oriented" and able simple and clean non-verbose objects. Java is verbose and force non-simple solutions, but C dont provide special mechanism to build and use objects, so everything is "user made"... Maybe horrible and ugly, but maybe not that ugly.

    </pedantic on bad english> 

     

  • (cs)

    I do believe it's a legend! It's no common to see people have a ratio bugs/line of code greater than 1!

  • (cs) in reply to GoatCheez

    GoatCheez:
    If anything, the WTF is that he didn't check that the merchant code was in the valid range. Below: the correct source for what "should" have been in the file. Note: I don't think that returning 0 for "true" is a wtf in itself without seeing other code from the library. A standard include file for this project could simply have #define TRUE 0 #definre FALSE 1.

    Sure it is. Then if (TRUE) { do_something(); } doesn't do anything. Unless you also #define IF(x) if (!(x)).
     

  • (cs) in reply to navigator
    navigator:
    WTF # 3: args to fread are reversed (10000, 1), making line (9) wrong

    How do you know? It works fine if you count any file that isn't at least 10000 bytes long as invalid. 

  • (cs) in reply to Valdis Kletnieks
    Anonymous:

     Probably even more of a WTF waiting to happen.  Especially on filesystems that don't implement directory indexing, locating a specific file can be an O(n) operation, involving multiple disk I/O operations - on a Unixoid filesystem, each NNNN.merchant filename is 13 bytes plus a trailing null for 14, plus another 4 bytes or so for an inode number.  You're looking at a 180K directory, which is 43 4K blocks.  Better hope all 43 are kept hot in the in-memory cache.  Also,  on a Unix box, reading the directory will (unless you mounted the filesystem 'noatime') cause an update of the access time of the directory, which will force a disk write to update the time stored on disk.


    It turns out that often the performance is *far* better by creating a directory '5', a directory '6', a directory '7', and then touch '8.merchants". Then the code tries to open "5/6/7/8.merchants" this will result in at most 10 compares in each of 3 directories, rather than 10K against one. 

    Actually, most filesystems will just use a fixed-size filename buffer. On UNIX, that's 256 chars. In DOS, it's 11 chars (so long filenames will increase disk usage in FAT32, but anyone using that on a server deserves what they get). I'm not sure about the directory itself, but I suspect that's also the case.

    And 'often' really isn't that often anymore - modern filesystems (reiser/HFS[+x]?/probably NTFS) store the directory in a tree, so you waste more time by using lots of subdirectories.

  • (cs) in reply to KoFFiE
    Anonymous:


    That is not a WTF at all... On any decent system this is blazingly fast. For quick peeking at a file this is actually good practice, so you don't have too many files open or forget to close a few...

    I think the wtf's are more summed up by:

    • He allocates 10k on stack, which is quite a lot. Ok, on modern machines/os'es this is no problem but still... For any buffer above 1k, I consider using malloc as the saner option.
    • ....

    Yes, but wouldn't it be a lot nicer to just store the special merchant table in memory? Isn't that the sane option?

    Allocating 10k on the stack is no problem. It's only a really stupid idea if you call other functions which also allocate a ton on the stack. On a PowerPC, some compilers will also complain if you allocate a lot (32k I think) since it complicates accessing things on the stack.

    (for the record, OSX has a default stack size limit of around 640k, so it still is a problem unless you setrlimit())

    Malloc is worse for short-lived buffers, since you need to perform memory allocation (as opposed to just moving the stack pointer).

    And I should get back to work.
     

  • (cs)

    There are numerous WTF's in this one as menioned before.

    Like not doing any caching. But another one strikes me:

    Why doesn't the Former Programming Legend, use a bitmask to code the special/not so special  merchants. My guess is he doesn't know bitmasks.

    That also gives me a clue about his Legendhood... 

  • An apprentice (unregistered)

    Of course this would properly be done in a database:

    col_indcol_val
    1 NNNNYNNNYNNYYNYYNNNNYNN

    ...and a custom C program would retrieve data by reading raw binary database files.

  • Thomas (unregistered)

    If Scott has been programming such a crap for narly 30 years now, he must now be really good in programming crap.

  • Paul (unregistered) in reply to ang
    Anonymous:

    Yeah, looks like he's following old skool UNIX exit codes.  It's not really a stretch if you turn the wayback machine to the late 70's/early 80's.

    Sorry, but he doesn't get a get-out-of-jail-free card here. To quote from the C bible which defines the language ("The C programming Language", By Brian W. Kernighan and Dennis M. Ritchie, 1972), Chapter 3, Section 2: if-else:

    if (expression) statement1 else statement2

    The expression is evaluated; if it is true (that is, if expression has a non-zero value), statement1 is executed. If it is false (expression is zero) and if there is an else part, statement2 is executed instead.

    So returning 0 for true in C in any decade is definately a fully bona fide WTF!!!

  • Anonymous Coward (unregistered) in reply to Arachnid
    Anonymous:

    Everyone seems to have missed a WTF in this line:

      fln = fread(&filedat, 10000, 1, file);
     filedat is a char*. Therefore, &filedat is a char**, and fread will dump its data all over the pointer and everything following it, rather than the character array the pointer points to. There's no way this code could ever have run successfully.	

     

    Good hit Anon - I just noticed this before I reached your post in the thread. It's lucky that fread never returns success, otherwise trying to use filedat will get you whatever happens to be at address "Y" or "N"!

    I think that whetever follows filedat will actually be the 10k bytes, otherwise this would have overwritten something more important on the stack and this would have surely never run?
     

  • Baughn (unregistered) in reply to no name
    Anonymous:

     

    Let me fix that for you:

     

    int is_special_merchant(int merchnum) 
    {
    size_t fln;
    char filedat[10000];
    FILE *file;

    if ((file=fopen("spcmerch.cfg","r" )) == NULL ) return(1);
    fln = fread(&filedat, 1, 10000, file) - 1;
    fclose(file);

    if (fln < merchnum) return(1);
    if(filedat[merchnum] == 'Y') return(0);

    return(1);
    }

     

     

    Let me fix that for you...

    int is_special_merchant(int merchnum) {

      FILE *file=fopen("spcmerch.cfg", "rb");

      if (file == NULL) return -1;

     
     

    Let me fix that for you...

    int is_special_merchant(int merchnum) {
      FILE *file=fopen("spcmerch.cfg","rb");
      if (!file) return -1;
      if (fseek(file, SEEK_SET, merchnum)) {
        fclose(file);
        return -1;
      }
      int ch=fgetc(file);
      fclose(file);
      if (ch == 'Y') return 1;
      if (ch == 'N') return 0;
      return -1;
    }
    
  • (cs) in reply to Lurker
    Anonymous:
    actually, unless Alex made a typo and reversed the arguments to fread, this procedure will return completely _defined_ results when confronted with a 23byte file, it'll claim that the merchant is not special, because the return value of "fread" will be 0
    fread returns the number of _objects_  read, given the specified argument order fread(buf,10000,1,file), an object is defined as being 10000 bytes long, since the file only contains 23 byte it doesn't contain a single (complete) object and thus the return value will be 0.
      

    Nice one.  If you take that a stage further. it means that even with a valid cfg file of 9999 entries, the return value will always be 0.

  • (cs) in reply to shadowman
    shadowman:
    Anonymous:
    Anonymous:
    The the WTF is the name doesn't match the function? I understand that false in C is 0, and true is non-zero. So he returns true is the person in not a special merchant when the function is called is_special_merchant.
    Follows UNIX-style exit codes maybe? I don't know, I'm stretching it a bit here. 
    Yeah, seems off, because:
        if (is_special_merchant(myMerchant)) {
           //whatever
        }
    will evaluate to true if the myMerchant is NOT a special merchant.

    I'm sure Scott always invokes that function through the special macro,

    #define IS_SPECIAL_MERCHANT(arg) (is_special_merchant(arg) == 0)

    and Alex neglected to show us the comment immediately preceding the function,

    /* This function must ALWAYS be invoked using the special macro IS_SPECIAL_MERCHANT */

  • Erlend (unregistered) in reply to Hit

    Anonymous:
    Well, let's see here.

    1.  No attempt at returning any kind of error codes. If it can't open the file, then nobody is a special merchant.
    2.  The same file is opened over and over again for every single line/transaction.  With caching I guess this isn't a HUGE deal, but still it's horribly inefficient.
    3.  Any merchantnum > 22 will return 0 or 1 depending on what "garbage" is in the allocated memory.  Odds are heavy it will be 1, but if there just happens to be a "Y" there...
    5.  ab is declared for no reason.  
    6.  Any merchantnum > 10000 will just simply core dump/IPF depending on operation system.

    Beautiful.
     

    I think that 3 is actually the reason he inversed the true/false logic of this method, when a merchantnum is greater than 22, he wanted false, but always got true, he reversed the logic true/false and he presto ! He 'just' forgot to rename his method, big deal ;) Every now and then (very rarely) there's a merchan who is been treated as a special one, perhaps the merchant doesn't complain ...

    This guy it truly a legend, a legendary fool, but still a legend. Are you sure he ain't called Paul Brillant, or perhaps this guy is old enough to be her father ?

  • anonymous (unregistered) in reply to Paul

    Anonymous:

    So returning 0 for true in C in any decade is definately a fully bona fide WTF!!!

    Maybe is a ms-dos-ism, with case(ERRORLEVEL) in mind...  

    REM WINDOWS VISTA INSTALL SCRIPT  

    IF ERRORLEVEL 255 GOTO Label255
    IF ERRORLEVEL 254 GOTO Label254

    *
    *
    *
    IF ERRORLEVEL 2 GOTO Label2
    IF ERRORLEVEL 1 GOTO Label1
    GOTO Label0

    :Label255
    (commands to be executed at errorlevel 255)
    GOTO End

    *
    *
    *
    :Label1
    (commands to be executed at errorlevel 1)
    GOTO End

    :Label0
    (commands to be executed at errorlevel 0, or no errorlevel)

    :End
  • the internet (unregistered) in reply to Jason Roelofs
    Anonymous:

    Did no-one else catch the other WTF here?

     if ( ! is_special_mercant(merc_id) ){

        // DO SPECIAL MERCH STUFF 

    }
     

     He returns 0 for success and 1 for failure!!! WTF?!
     

    yeah, about a million people had mentioned that but good work

  • Anonymous (unregistered) in reply to Lurker

    You're right... The function will always return 1.  There's no such thing as a special merchant!  Oh well, on to the next function: is_easter_bunny().

  • Paul (unregistered) in reply to anonymous
    Anonymous:

    Anonymous:

    So returning 0 for true in C in any decade is definately a fully bona fide WTF!!!

    Maybe is a ms-dos-ism, with case(ERRORLEVEL) in mind...  

    REM WINDOWS VISTA INSTALL SCRIPT  

    IF ERRORLEVEL 255 GOTO Label255
    IF ERRORLEVEL 254 GOTO Label254

    WTF?  This is BASIC code, dude.

    Point is: if you are going to return an error code + don't want your code showing up here -- you don't call your function  <i>is_some_property(some_data)</i> 

  • The WonderBlogger (DAL) (unregistered)

    Perhaps I missed someone else's comment on this but...

     Did no one else catch the file that does not always get closed?

     if(fln == (size_t)0) return(1);
     fclose(file);

     If the first statement evaluates to true then the file never gets closed. The next time this method gets called the LOC that opens the file will fail, causing a value of 1 to be returned.

    The good news is that after this happens the results are no longer random! All merchants are special (and isn't this the case anyway?) Well. they're special to someone I'm sure....

  • JL (unregistered) in reply to Anonymous Coward
    Anonymous:
    Anonymous:

    Everyone seems to have missed a WTF in this line:

    fln = fread(&filedat, 10000, 1, file);
    filedat is a char*. Therefore, &filedat is a char**, and fread will dump its data all over the pointer and everything following it, rather than the character array the pointer points to. There's no way this code could ever have run successfully.

    Good hit Anon - I just noticed this before I reached your post in the thread. It's lucky that fread never returns success, otherwise trying to use filedat will get you whatever happens to be at address "Y" or "N"!

    I think that whetever follows filedat will actually be the 10k bytes, otherwise this would have overwritten something more important on the stack and this would have surely never run?

    I'm not sure what you meant by getting "whatever happens to be at address "Y" or "N"", but I suspect the code may "work" in spite of the error.

    The char array is stored on the stack, so "filedat" is an address in the stack.  Then "&filedat" must be the address of wherever this address is stored...  But it isn't being stored anywhere -- it's a value that gets used directly, so you can't take its address.  I suspect this is one of C's many undefined conditions; the compiler can probably return garbage (and really should flag it as an error).  But when I ran a quick test in MSVC, I found it behaving as Scott expected it: "filedat" and "&filedat" gave the same pointer value, even though one is "char*" and the other "char**"... Not even a warning.  Are there any C standards gurus out there that can shed more light on this?

  • Charles McCreary (unregistered) in reply to Lurker

    Bingo! This function always returns 1 since fread returns 0 (will return some number less than nitems and since nitems is 1, will return 0).  The only time this will work is when the file is indeed 10k+ characters.

  • Baughn (unregistered) in reply to JL
    Anonymous:
    Anonymous:
    Anonymous:

    Everyone seems to have missed a WTF in this line:

    fln = fread(&filedat, 10000, 1, file);
    filedat is a char*. Therefore, &filedat is a char**, and fread will dump its data all over the pointer and everything following it, rather than the character array the pointer points to. There's no way this code could ever have run successfully.

    Good hit Anon - I just noticed this before I reached your post in the thread. It's lucky that fread never returns success, otherwise trying to use filedat will get you whatever happens to be at address "Y" or "N"!

    I think that whetever follows filedat will actually be the 10k bytes, otherwise this would have overwritten something more important on the stack and this would have surely never run?

    I'm not sure what you meant by getting "whatever happens to be at address "Y" or "N"", but I suspect the code may "work" in spite of the error.

    The char array is stored on the stack, so "filedat" is an address in the stack.  Then "&filedat" must be the address of wherever this address is stored...  But it isn't being stored anywhere -- it's a value that gets used directly, so you can't take its address.  I suspect this is one of C's many undefined conditions; the compiler can probably return garbage (and really should flag it as an error).  But when I ran a quick test in MSVC, I found it behaving as Scott expected it: "filedat" and "&filedat" gave the same pointer value, even though one is "char*" and the other "char**"... Not even a warning.  Are there any C standards gurus out there that can shed more light on this?



    Sure thing. filedat is an array, and while the value of an array is indeed a pointer to its first element, the address-of operator doesn't operate on values.

    So.. &filedat is of type (char (*)[10000]), which is normally implemented as a pointer to the first element - that is, the same value as filedat.

    Different type, though, and I'm not sure it isn't UB to pass it to fread like that.
  • b (unregistered)

    it's a perfect code. i only miss the merchnum > fln and merchnum > filedat_size checks, but otherwise it's simple and it works. as someone said: enterprise solution :-)

  • (cs) in reply to GoatCheez
    GoatCheez:

    Somehow I don't think this code is as big of a WTF as being claimed, or if it's a WTF at all.

    Merchant codes are at max 4 digits, meaning the largest merchant code would be 9999. He allocated 10000 bytes for his buffer. Perfect. It works perfect for the  current spec. fread attempts to read that many bytes. It'll read as many as it can, so good. He doen't check that the merchant code is greater than the length of the file. That COULD be a wtf.... No, frankly this code isn't that bad. Sure, if it encounters an error it'll return 1, but that's the worse it'll do. Just make sure the mechant codes start at 0 and increment from there.

     

    Sometimes I say really retarded things, and then  keep on saying more retarded things, until I've reached a state of total retardation.... I was really retarded yesterday lol.

  • (cs) in reply to Arachnid
    Anonymous:
    filedat is a char*. Therefore, &filedat is a char**, and fread will dump its data all over the pointer and everything following it, rather than the character array the pointer points to.

    Nonsense! filedat is not a char *, it is a char[10000]. That is not the same thing as a char * in C, although it is implicitely convertible. &filedat in this context is exactly the same as filedat.

    If you don't believe me, try it for yourself:

    #include <stdio.h>
    
    int main(void) {
        char myarr[10000];
        printf("%p\n", myarr);
        printf("%p\n", &myarr);
    }
    

    Output on the system I tested this on:

    0x22a5d0
    0x22a5d0
    

    In fact, there is no named pointer object involved at all! For instance, "& &myarr" (which would be a char **) will fail to compile because "&myarr" is not an lvalue. How exactly do you take the address of a pointer that doesn't exist?

    PS: The forum software inserts <br/> tags in <pre> sections. WTF?

  • (cs) in reply to The WonderBlogger (DAL)
    Anonymous:

    Perhaps I missed someone else's comment on this but...

     Did no one else catch the file that does not always get closed?

     if(fln == (size_t)0) return(1);
     fclose(file);

     If the first statement evaluates to true then the file never gets closed. The next time this method gets called the LOC that opens the file will fail, causing a value of 1 to be returned.

    The good news is that after this happens the results are no longer random! All merchants are special (and isn't this the case anyway?) Well. they're special to someone I'm sure....



    1) Plenty of people have already noted that the file never gets closed, hence leaking file handles all over the place. Perhaps you could try reading the existing comments before posting?

    2) Why do you think the second and subsequent fopen()s will fail? Is the file is not sharable for some reason, even when being opened only to read?
  • Anonymous (unregistered) in reply to The Anonymous Coward

    Even IF the data were being read correctly (i.e. there were enough of it and fread was beign called correctly). It's still undefined behaviour. And that's a bad thing with my credit card.

  • Mike Miller (unregistered) in reply to navigator

    navigator:
    Not necessarily; you are thinking in decimal. This guy is a legend in his own mind - maybe he thinks in hex, so 4 digits would be: 0..63K-1</smirk>

    I wouldn't smirk just yet. Hex lets you go up to 64K-1 if K=1024, or 65.535K if K=1000.

     

  • JL (unregistered) in reply to Baughn

    Anonymous:

    Sure thing. filedat is an array, and while the value of an array is indeed a pointer to its first element, the address-of operator doesn't operate on values.

    So.. &filedat is of type (char (*)[10000]), which is normally implemented as a pointer to the first element - that is, the same value as filedat.

    Different type, though, and I'm not sure it isn't UB to pass it to fread like that.

    Thanks, but I guess I still don't understand where this behavior would be useful instead of an error. After all, it isn't giving you the address of the variable, which is the purpose of the address-of operator.  Generally I'd expect "a == *(&a)" to be true when it isn't an outright syntactic error, but in this case it doesn't hold.  Instead "filedat == &filedat", and "*(&filedat)" is a garbage pointer value formed from whatever character data happens to be stored in filedat.

  • Anonymous (unregistered) in reply to anonymous

    Anonymous:
    But a lang can be "oop oriented"

    "Object-oriented programming oriented?"

  • Tox (unregistered) in reply to DigitalLogic

    what are you? a Java programmer? you should read borland manuals more

  • (cs) in reply to Anonymous Coward
    Anonymous:
    Anonymous:

    Everyone seems to have missed a WTF in this line:

      fln = fread(&filedat, 10000, 1, file);
     filedat is a char*. Therefore, &filedat is a char**, and fread will dump its data all over the pointer and everything following it, rather than the character array the pointer points to. There's no way this code could ever have run successfully.	

     

    Good hit Anon - I just noticed this before I reached your post in the thread. It's lucky that fread never returns success, otherwise trying to use filedat will get you whatever happens to be at address "Y" or "N"!

    I think that whetever follows filedat will actually be the 10k bytes, otherwise this would have overwritten something more important on the stack and this would have surely never run?
     

     

    Not really a WTF. I think the compiler does an implicit cast from char[] to void *. Adding the extra & doesn't change the outcome. I actually was surprized to find this out. Test it yourself:

     

    void printit(void *ptr)
    {
        printf("%p\n", ptr);
    }

    int main()
    {
        char buffer[42];

        printit(buffer);
        printit(&buffer);

        return 0;
    }

     

    Outputs:

    0012F544
    0012F544

    (Tested with MS VC++) 

  • anonymous (unregistered)

    Someone else said it right the first time --- it's not too bad of an idea, but the implementation greatly misses the mark.   Let me enumerate the ways.........    (anyone here know anything about Unix?   Apparently not!)

     

    • fln is always going to be zero.   He's reading 10000 bytes from a 23 byte file.    He's not using feof() to check the results.   It's going to be feof(file)==1, ferror(file)==0, fln==0.   (if his fread was 23 bytes, fln would = 1)
    • Since fln==0, it's always going to return 1
    • Since fln==0, it's never going to close the file.
    • Since it never closes the file, it's probably going to quit after 1024 times (most unices give a default ulimit -n of 1024).   
    • So after opening 1024 files, it's not even going to bother opening the file any longer and just return 1.


    Hello?   Yea, this is a REAL WTF --- for anyone who knows anything about Unix systems!

     

     

  • BtM (unregistered) in reply to JL
    Anonymous:

    Anonymous:

    Sure thing. filedat is an array, and while the value of an array is indeed a pointer to its first element, the address-of operator doesn't operate on values.

    So.. &filedat is of type (char (*)[10000]), which is normally implemented as a pointer to the first element - that is, the same value as filedat.

    Different type, though, and I'm not sure it isn't UB to pass it to fread like that.

    Thanks, but I guess I still don't understand where this behavior would be useful instead of an error. After all, it isn't giving you the address of the variable, which is the purpose of the address-of operator.  Generally I'd expect "a == *(&a)" to be true when it isn't an outright syntactic error, but in this case it doesn't hold.  Instead "filedat == &filedat", and "*(&filedat)" is a garbage pointer value formed from whatever character data happens to be stored in filedat.

    A value of an array type is implicitly converted to a pointer to the base type unless:

    • The array is an argument to either the sizeof or address-of (&) operators
    • A character string literal is used to initialize a character array
    • A wide string literal is used to initialize an array of type wchar_t

    In this case, the implicit conversion to a pointer type doesn't happen because of the presence of the & operator, so for this particular context, filedat really does == &filedat. And the result is implicitly converted to type void* when passed to fread()  anyway. 

    It looks and feels like a real WTF, but at worst it's just bad style (it's something I wouldn't do, anyway). 

    Captcha = "paula".

  • (cs) in reply to Coditor
    Anonymous:

    Today's question: Java is OOP, C is OOP, so together are they OOPS?

    Best quote ever!

  • (cs) in reply to flavius

    Lots of people seem to be assuming that the file is actually too short.  Just because they assign a 4-digit merchant number doesn't mean they have 9999 merchants...

    Honestly, with code of this quality and where dealing with credit cards, the real WTF is surely that they have managed to retain 23 clients?

    Simon 

Leave a comment on “Legendary Configuration”

Log In or post as a guest

Replying to comment #:

« Return to Article