- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
<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>
Admin
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
Admin
Well, If he does it by hand, he deserves whatever ribbing he gets.
Admin
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
Admin
And which ones are special?
Admin
LOL
Its nice to c-code in a wtf, finally something an old-timer can understand :)
captcha null LOL!Admin
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.
Admin
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.
Admin
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 :-)
Admin
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?
Admin
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...
Admin
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... :DAdmin
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.
Admin
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>
Admin
I do believe it's a legend! It's no common to see people have a ratio bugs/line of code greater than 1!
Admin
Sure it is. Then if (TRUE) { do_something(); } doesn't do anything. Unless you also #define IF(x) if (!(x)).
Admin
How do you know? It works fine if you count any file that isn't at least 10000 bytes long as invalid.
Admin
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.
Admin
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.
Admin
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...
Admin
Of course this would properly be done in a database:
...and a custom C program would retrieve data by reading raw binary database files.
Admin
If Scott has been programming such a crap for narly 30 years now, he must now be really good in programming crap.
Admin
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:
So returning 0 for true in C in any decade is definately a fully bona fide WTF!!!
Admin
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?
Admin
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...
Admin
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.
Admin
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 */
Admin
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 ?
Admin
Maybe is a ms-dos-ism, with case(ERRORLEVEL) in mind...
Admin
yeah, about a million people had mentioned that but good work
Admin
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().
Admin
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>
Admin
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....
Admin
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?
Admin
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.
Admin
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.
Admin
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 :-)
Admin
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.
Admin
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:
Output on the system I tested this on:
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?
Admin
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?
Admin
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.
Admin
I wouldn't smirk just yet. Hex lets you go up to 64K-1 if K=1024, or 65.535K if K=1000.
Admin
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.
Admin
"Object-oriented programming oriented?"
Admin
what are you? a Java programmer? you should read borland manuals more
Admin
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:
Outputs:
(Tested with MS VC++)
Admin
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!)
Hello? Yea, this is a REAL WTF --- for anyone who knows anything about Unix systems!
Admin
A value of an array type is implicitly converted to a pointer to the base type unless:
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".
Admin
Best quote ever!
Admin
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