Accidentally Overwriting Another Local Variable in C and C++
blog.petrzemek.net
blog.petrzemek.net
Thinking about it more you don't even need the parameter, just declare a local variable, take its address and go crazy. With great power (it's a systems programming language) comes great responsibility.
Wow, this is the most Hacker News comment I think I've ever posted, maybe I need to quit Hacker News :-).
If you go one layer below with some assembly, you don't even need variables. Just take the stack pointer register (rsp on amd64) and start writing!
Or maybe no assembly needed, just cast an arbitrary hexadecimal value you think is likely to be in range to be your stack pointer [may vary by platform, ASLR, how many frames are on the stack, etc.] into a pointer and go to town.
You need either a static type system, or a runtime that'll catch weird accesses and throw immediately. A dynamic but happy to corrupt memory interface boundary is just crazy town.
Okay, sure.
> ...as I crush some mad code, braugh
What? I've never run into this. How does this have anything to do with opinions on types again? It sounds like you have an axe to grind.
> The company later described it as a joke and as an unfortunate misstep.
"It's just a joke, bro"
If your system defines NULL as 0, which is legal in C++, then NULL in the vararg list only pushes an int-sized (4 bytes) zero, and the vararg reader pulls a pointer-sized (8 bytes) value, which may or may NOT equal zero because of the 4 extra bytes...
extern int
my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
(Now I like rust's solution better, a sane macro system so this interface doesn't have to be special cased by the compiler to be safe). __attribute__ ((format (printf, 1, 2)))
static inline std::string format(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
size_t bytes = vsnprintf(0, 0, fmt, args);
va_end(args);
va_list again;
va_start(again, fmt);
std::string result(bytes, '\0');
vsnprintf(&result[0], bytes + 1, fmt, again);
va_end(again);
return result;
}C++ has references which won't suffer from this, and containers and such to avoid sprintf()-class bugs. But if you're still writing C++ code while thinking of C there isn't much C++ can do about it.
In valgrind 3.7.0, you can use the experimental engine exp-sgcheck to look for stack and global overruns. ( valgrind command line parameter --tool=exp-sgcheck ). It is experimental and doesn't always work, but might have in this case.
2. something like CRT or dmalloc to catch the leak. not perfect but a good hint
And valgrind didn't find the leak, so dlmalloc or CRT def would not have.
I used to work on a library. You wouldn't believe how long some people held onto RHEL 5... And I had to maintain ABI compatibility with the standard system compiler on each supported OS.
Lots of stuff is just a typedef if the C struct in a namespace. Classes that do work all have private constructors and static member functions that return a new'd pointer to the object. They also have static member functions to deallocate the objects.
Thanks for the C++ wrapper assholes. Your C++ wrapper looks more like C than the C library it's wrapping.
Greenfield C++ (or anything that was greenfield with C++11 in mind) is a joy to write. Idiomatic C in C++ or idiomatic Java in C++ is terrible. The fact that you can write so many different styles is probably the reason the language is so ubiquitous, but it sure sucks a lot more to deal with other people's shitty code in C++ than in many other languages.
I don't know why you call them assholes, they are just being themselves, limitations and all, and providing a fairly amusing story for you to tell.
In practice, I've had far less issues working with modern C++ codebases than with modern Java codebases.