|
That Turkey Story posted:It's mostly due to the fact that prior to C++11 there was no way to create "variadic templates" (templates that can take any number of parameters). The hilarious thing about MSVC is that there actually still isn't real variadic template support in VS2012 - they use 'faux variadics.' The following paragraph speaks for itself: quote:Faux variadics: We've developed a new scheme for simulating variadic templates. Previously in VC9 SP1 and VC10, we repeatedly included subheaders with macros defined differently each time, in order to stamp out overloads for 0, 1, 2, 3, etc. arguments. (For example, <memory> included the internal subheader <xxshared> repeatedly, in order to stamp out make_shared<T>(args, args, args).) In VC11, the subheaders are gone. Now we define variadic templates themselves as macros (with lots of backslash-continuations), then expand them with master macros. This internal implementation change has some user-visible effects. First, the code is more maintainable, easier to use (adding subheaders was a fair amount of work), and slightly less hideously unreadable. This is what allowed us to easily implement variadic emplacement, and should make it easier to squash bugs in the future. Second, it's harder to step into with the debugger (sorry!). Third, pair's pair(piecewise_construct_t, tuple<Args1...>, tuple<Args2...>) constructor had "interesting" effects. This requires N^2 overloads (if we support up to 10-tuples, that means 121 overloads, since empty tuples count here too). We initially observed that this (spamming out so many pair-tuple overloads, plus all of the emplacement overloads) consumed a massive amount of memory during compilation, so as a workaround we reduced infinity. In VC9 SP1 and VC10, infinity was 10 (i.e. "variadic" templates supported 0 to 10 arguments inclusive). In the VC11 Developer Preview, infinity is 5 by default. This got our compiler memory consumption back to what it was in VC10. If you need more arguments (e.g. you had code compiling with VC9 SP1 or VC10 that used 6-tuples), there's an escape hatch. You can define _VARIADIC_MAX project-wide between 5 and 10 inclusive (it defaults to 5). Increasing it will make the compiler consume more memory, and may require you to use the /Zm option to reserve more space for PCHes.
|
# ? May 8, 2013 20:15 |
|
|
# ? Jun 5, 2024 07:27 |
|
Other "hilarious" things in MSVC include the fact that you can't capture a variable through nested lambdas unless you rename it, and using the auto keyword in C++/CLI code crashes the compiler.
|
# ? May 8, 2013 20:21 |
|
GrumpyDoctor posted:using the auto keyword in C++/CLI code crashes the compiler. ahaha what?
|
# ? May 8, 2013 20:25 |
|
GrumpyDoctor posted:Other "hilarious" things in MSVC include the fact that you can't capture a variable through nested lambdas unless you rename it, and using the auto keyword in C++/CLI code crashes the compiler. To be fair, everything in C++/CLI is broken.
|
# ? May 8, 2013 20:25 |
|
And isn't WinRT supposed to use C++/CLI?
|
# ? May 8, 2013 20:27 |
|
No, it uses C++/CX which is completely different from C++/CLI
|
# ? May 8, 2013 20:28 |
|
hieronymus posted:The hilarious thing about MSVC is that there actually still isn't real variadic template support in VS2012 - they use 'faux variadics.' The following paragraph speaks for itself:
|
# ? May 8, 2013 20:30 |
|
tractor fanatic posted:ahaha what? Looks like it might just be with static members of ref classes, but come on.
|
# ? May 8, 2013 20:37 |
|
Friend in college asked me to look at his code, had a bug he couldn't figure out. All of the variables were named as single alphabet characters. Refused to look into it until he had proper variable names, and what do you know? Problem sorted itself out. I guess that's just laziness? Ugh. How do you live with that?
|
# ? May 8, 2013 20:41 |
|
That Turkey Story posted:It's mostly due to the fact that prior to C++11 there was no way to create "variadic templates" (templates that can take any number of parameters).
|
# ? May 8, 2013 20:51 |
|
Victor posted:Ahh, this makes more sense. Oddly enough, I was wondering about whether variadic templates were possible last night. Pre-C++11, I'd probably have made the decision based on how likely my dependence on them would result in horrible error messages. My experience with dealing with the CPP is that it's a PITA; are there ways of doing it that aren't obtuse? Even using C++ templates to do metaprogramming is obtuse; it's pretty hilarious to see my boss' ML code that explains what the templates are doing. Quite a bit more concise! Unless the language completely changes, compile-time metaprogramming will always be a mess. Even features like constexpr do very little for anything but trivial metaprograming tasks.
|
# ? May 8, 2013 21:01 |
|
Zaphod42 posted:Friend in college asked me to look at his code, had a bug he couldn't figure out. I had a friend in college who used pokemon names.
|
# ? May 8, 2013 22:45 |
|
shrughes posted:I had a friend in college who used pokemon names. I knew someone in college who programmed with a font that had the same glyph for 1, l, and I.
|
# ? May 8, 2013 22:54 |
|
That Turkey Story posted:Unless the language completely changes, compile-time metaprogramming will always be a mess. Even features like constexpr do very little for anything but trivial metaprograming tasks.
|
# ? May 8, 2013 23:32 |
|
tractor fanatic posted:Groups are in any abstract algebra class though, so you certainly don't need to go as far as category theory to encounter them. I'm not taking abstract algebra in my degree though. I've seen everything that other guy mentioned, as well as poo poo like graphs, FSMs and recurrence relations. And I think a little bit on formal languages.
|
# ? May 9, 2013 00:24 |
|
That Turkey Story posted:Of course, this leaves you with people like myself, who would gladly use libraries like the tuple library back in the early 2000s because it's a tool that fits our needs, and people like Suspicious Dish (not meant as an insult) that do not want to use these libraries because of all of the hackiness going on behind the scenes -- What happens if something goes wrong? Do I want to have to trudge through preprocessor code? Is using the tool worth the other potential headaches? There's a bit of a gray area in there between you and Suspicious Dish. I think it's fine to use metaprogramming stuff from a proven and maintained library like boost, although there are bits of boost I dislike. For instance, the other day I used tuple and boost::any to make a dispatch table. Boost's documentation is generally ok and so far I've been able to figure out any boost usage I've encountered. The thing I don't like is when people go way down the template and preprocessor rabbit hole on their own and leave a giant, undocumented, impossible to maintain wart in the codebase. I recently ripped out what was undoubtably someone's baby -- a DSL for implementing an XML schema binding. It was sort of a nightmarish jaxb. It was quite clever, it even included the ability to write an xsd for an object. Thing was, while the developer had made great strides to allow the representation of maps, vectors, and all the basic types, that was where the flexibility stopped. Want a map of vectors or a map of a map of something? Go into the lib and implement it yourself. Some bad decisions were being made regarding the design of the XML being used by this thing because the framework didn't support more complex data structures. There were other blotches too. It wrote all of its XML via boost serialization instead of with a real XML lib like Xerces. This occasionally caused problems. Worst of all, the DSL for specifying the data structure was completely undocumented, the developer is long departed and in house as well as third party devs were expected to figure it out with the aid of only a sparse example. You should see some of the crap code some third party interns working with this thing churned out. Thank god it's gone. I've switched out the xml for json with the wjelement library. C++ json support is pretty woeful. Thankfully, wjelement is pretty kickin' rad. It even has json schema support and an xpath-like selector syntax. It's documentation has some holes but at least it has documentation. C++ metaprogramming is not inherently bad, it's just really really easy for it to get messy and unmaintainable. If it's going to be done at all it should be done with the aid of boost since boost abstracts away most of the mess and provides docs. If you're doing it without boost then you better be unit testing and documenting it so hard because otherwise in the future it will confuse the piss out of some poor intern or re-purposed C programmer.
|
# ? May 9, 2013 02:00 |
|
Here's a special present from one of our support engineers. (Lack of) indentation preserved: select * from data_table where id_a in ( select id_a from table_a where id_b in ( select id_b from table_b where id_c in ( select id_c from table_c where relevant_field = criteria)) ) and (timestamp > sysdate - 12) and (timestamp < sysdate-6)
|
# ? May 9, 2013 02:10 |
|
I think the example on this page counts as a documentation horror. Just leave it out, guys.
|
# ? May 9, 2013 02:21 |
|
GrumpyDoctor posted:I think the example on this page counts as a documentation horror. Just leave it out, guys. Seeing http://www.contoso.com brought back a strange rush of nostalgia and hate
|
# ? May 9, 2013 04:06 |
|
After 4 months of being here (I'm on an 8 month co-op (that thing I said about only having 3 semesters left? I'm expecting to finish in April 2015)), I think I have something worthy of this thread.code:
Some of that isn't verbatim, e.g. it actually prints error messages. It turns out that number is BUF_LEN in size every time this function is used, but using that instead of the size parameter when copying the result into the output buffer is BAD. Not to mention the stuff in the for loop that only needs to be done once. I basically rewrote much of it, it's sitting in code review right now. I was told to put the original author on the review request because he needs to learn how to code better.
|
# ? May 9, 2013 15:26 |
|
The code you posted is a horror but I'm not sure what it is supposed to do. I trust you removed the bits where it branches based on values in uninitialized memory?
|
# ? May 9, 2013 15:35 |
|
It's supposed to ask the user to enter a number. I left outcode:
|
# ? May 9, 2013 15:43 |
|
zergstain posted:It's supposed to ask the user to enter a number. I left out Yeah, it looked like the if clause was operating on retval and answer without them ever having been initialized.
|
# ? May 9, 2013 16:01 |
|
My main duty is fixing issues flagged in static analysis. It seems half the developers think you need to check for NULL before freeing, and often that's the only place they check, so the static analyzer goes when the pointer is used because apparently the programmer thinks it could be NULL and forgot to handle it. Most of the time it will never be NULL because it errors out if malloc fails, or we use our xmalloc function which calls malloc in an infinite loop until malloc succeeds. Most of the issues I fix aren't like that, but that one is pretty common. They also cast the free() argument to char *, what would make someone think this is necessary?
|
# ? May 9, 2013 17:55 |
|
zergstain posted:our xmalloc function which calls malloc in an infinite loop until malloc succeeds. hey I found a horror
|
# ? May 9, 2013 18:04 |
|
|
# ? May 9, 2013 18:21 |
|
Even once I take my brain out of the "my kilobytes " mode, that's still insane. And also that is the opposite of what xmalloc is supposed to do!
|
# ? May 9, 2013 18:23 |
|
How did anyone think that was a good idea.
|
# ? May 9, 2013 18:24 |
|
JawnV6 posted:hey I found a horror It sleeps the thread for 1 second. I don't know if you were thinking it just spins. Scratch the part about it erroring out if malloc() fails, the analyzer would know that it couldn't get to the line that dereferences the pointer, so it wouldn't flag it.
|
# ? May 9, 2013 18:24 |
|
zergstain posted:They also cast the free() argument to char *, what would make someone think this is necessary? I can answer this, C didn't always have void *. I guess if you learned C at Berkeley in the 70s you'd pick up that habit. On the other hand, K&R C didn't have typed arguments for functions either, so the cast is only relevant where pointers are a different size from int VVVV Young whipper-snapper, what are these "argument types" you talk about? All functions take a variable number of int arguments, of course! And malloc returns int, too, of course: stdlib.h? what's that?! just type "malloc", let the linker sort it out! (by the way, did you ever notice almost all C runtime function names are 6 characters or less...?) hackbunny fucked around with this message at 18:52 on May 9, 2013 |
# ? May 9, 2013 18:41 |
|
zergstain posted:Most of the issues I fix aren't like that, but that one is pretty common. They also cast the free() argument to char *, what would make someone think this is necessary? I believe that in the pre ANSI-C days, void * wasn't a type so free took a char * which you'd need to manually cast to. It's the same reason that some people still do this cast code:
|
# ? May 9, 2013 18:43 |
|
You also have to do that cast in C++
|
# ? May 9, 2013 18:49 |
|
hackbunny posted:I can answer this, C didn't always have void *. I guess if you learned C at Berkeley in the 70s you'd pick up that habit. On the other hand, K&R C didn't have typed arguments for functions either, so the cast is only relevant where pointers are a different size from int Yeah, I think most of the code like that was written in the mid 1990s, so maybe these guys graduated 20 years before that, and kept the habit.
|
# ? May 9, 2013 18:52 |
|
hackbunny posted:On the other hand, K&R C didn't have typed arguments for functions either, so the cast is only relevant where pointers are a different size from int If I recall correctly, this is actually a characteristic of pre-K&R C, where all arguments were assumed to be word sized and no type checking had been done a la BCPL and B. In K&R, you have typed arguments, but they're declared a little differently: code:
|
# ? May 9, 2013 18:52 |
|
Rothon posted:I believe that in the pre ANSI-C days, void * wasn't a type so free took a char * which you'd need to manually cast to. It's the same reason that some people still do this cast I do that, years of programming with compilers of varying age and quality have left me with all sorts of habits. (In actual practice tho I'd do code:
|
# ? May 9, 2013 18:53 |
|
Otto Skorzeny posted:If I recall correctly, this is actually a characteristic of pre-K&R C, where all arguments were assumed to be word sized and no type checking had been done a la BCPL and B. They are typed and named in the definition. The declaration would simply be: code:
E: this is still relevant in modern C due to variadic functions, and it leads to heaps of fun where sizeof(void *) != sizeof(int). You'd better hope nobody is passing 0 as a null pointer literal to a variadic function when you have to port to a 64-bit platform hackbunny fucked around with this message at 19:07 on May 9, 2013 |
# ? May 9, 2013 18:57 |
|
zergstain posted:It sleeps the thread for 1 second. I don't know if you were thinking it just spins. This was not the correct answer.
|
# ? May 9, 2013 19:00 |
zergstain posted:It sleeps the thread for 1 second. I don't know if you were thinking it just spins. Okay one of your threads is spinning like that. Now another thread needs to make an allocation. It starts spinning too. A third thread, which happens to already be sitting on a significant amount of memory, needs a bit more. Guess what happens. Now all of your threads are poking at the memory manager constantly, like little kids with their rooms bursting full of toys, begging their poor mom for more.
|
|
# ? May 9, 2013 19:03 |
|
It's OK - it only keeps going until someone notices the process isn't responding and kills it and they probably have a script for that.
|
# ? May 9, 2013 19:24 |
|
|
# ? Jun 5, 2024 07:27 |
Munkeymon posted:It's OK - it only keeps going until someone notices the process isn't responding and kills it and they probably have a script for that. But you know, it'd be great if it could, like, just die all on its own if something like that happened, right?
|
|
# ? May 9, 2013 19:34 |