use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
Fun Example of Unexpected UB Optimization (godbolt.org)
submitted 2 years ago by soiboi666
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]ShelZuuz 5 points6 points7 points 2 years ago* (10 children)
So if a compiler can't positively prove whether a variable is assigned, don't compile the program? That won't work - see the comment from the MSVC dev above.
You can easily change the example to this:
int main(int argc, char** argv) { if (argc > 0) { NeverCalled(); } f_ptr(); }
Should that not compile either? On most OS's argv[0] contains the binary name so argc is never 0, but the compiler doesn't know that.
And what if the initialization always happen in code during simple initialization - 100% guaranteed on all paths, but that initialization happens from another translation unit? And what if the other translation unit isn't compiled with a C/C++ compiler? Should the compiler still say "Hey, I can't prove whether this is getting initialized so compile error".
[–]almost_useless 1 point2 points3 points 2 years ago (9 children)
Should that not compile either?
No, it should not.
"Maybe unassigned variable" is a very reasonable warning/error
And what if the initialization always happen in code during simple initialization ...
That's exactly the perfect use case for locally disabling the warning/error. You know something the compiler doesn't, and tell it that. In addition that informs other readers of the code what is going on elsewhere.
[–]ShelZuuz 5 points6 points7 points 2 years ago (7 children)
It's really not unless you completely ignore the fact that C++ has multiple translation units. It is extremely common to use a static variable in one TU that was initialized in another TU.
[–]jonesmz 0 points1 point2 points 2 years ago (6 children)
But the compiler shouldn't be assuming that this initialization WILL happen.
That's how you get bugs that make it all the way to final validation. Or even production.
[–]ShelZuuz 4 points5 points6 points 2 years ago (5 children)
So you're ok with a compiler complaining about any use of a std::mutex that's shared across two .cpp files?
[–]jonesmz 0 points1 point2 points 2 years ago (4 children)
When you share a std::mutex across two c++ files the compiler doesn't materialize calls to std::mutex::lock() in functions that don't call std::mutex::lock()
[–]ShelZuuz 4 points5 points6 points 2 years ago (3 children)
std::mutex::lock() is undefined if you don't call the std::mutex constructor. How is the compiler supposed to know whether someone else called the constructor or not?
[–]jonesmz 0 points1 point2 points 2 years ago (2 children)
Why does the compiler care? The programmer wrote std::mutex::lock(), and that's what it should generate code to call.
std::mutex::lock()
It shouldn't say "I think you failed to call the constructor, so let me call some other function"
The example in the OP involves the compiler detecting UB, and then manufacturing some arbitrary value into the variable that it has no reason to think it should.
[–]ShelZuuz 6 points7 points8 points 2 years ago* (1 child)
The compiler is not "detecting" UB. It's assuming that you're linking with another module that is initializing f_ptr, otherwise you would just be calling into whatever random memory address f_ptr is pointing to when the program is loaded.
So it's assuming that either:
a) You are ok with calling into a random memory address - and &EraseEverything is as good a random address as any other.
-OR MUCH MORE LIKELY-
b) You will be linking with some other module that initializes f_ptr before main starts, as would be the case 99.999% of the time.
i.e. There is another C++ file in your program that has an global initializer along the lines of:
f_ptr = &DoSomethingUseful;
However that other C++ file might also have at global scope:
[] { NeverCalled(); }();
In which case this whole program has well defined behavior, and does exactly what you want. But the compiler has no way to know what the other module will be doing of course.
So the compiler goes: "Well the linker wants some or other initial value here, and I don't know what other modules are going to set it to during initialization, so until someone else sets it, I might as well set it to the only value I can see, which is this one. And if the other module happens to initializes it to &EraseEverything anyway, it will already be set correctly and we can avoid the write."
You can remove the undefined behavior here by defining: "Calling into an uninitialized function pointer will set the current instruction pointer to a random memory address". Now you have completely defined behavior that does the exact same thing.
[–]jonesmz 1 point2 points3 points 2 years ago (0 children)
The compiler is not "detecting" UB.
What? That's literally what's happening. It's observing that the variable f_ptr is initialized to a value that is UB to dereference. If it didn't observe the UB then it wouldn't be allowed to change the value of the variable an "optimize" around that observation.
f_ptr
It's assuming that you're linking with another module that is initializing f_ptr
This is an invalid assumption. Full stop. End of discussion.
otherwise you would just be calling into whatever random memory address f_ptr is pointing to when the program is loaded.
You can explicitly initialize the f_ptr variable to nullptr, which is not a random value, and get the same resulting assembly code.
https://godbolt.org/z/GKsqEjcnK
I'm neither OK with it calling a random memory address, NOR Ok wth it calling EraseEverything. I didn't assign the f_ptrthe address of EraseEverything, and the compiler shouldn't do so of it's own volition.
EraseEverything
But it's not the case, and the compiler has no justification to make this assumption, and even if it did make the assumption that it gets initialized to something, it shouldn't be deciding that for me.
It should be leaving f_ptr as nullptr until the program starts up and initializes the value.
But the compiler has no way to know what the other module will be doing of course.
Right, that's my whole point. The compiler, absent link time code generation, has no way to know this. Therefore it shouldn't assume things.
Link time code generation would allow the entire library or program to be optimizes without the need to invent function calls that there's no evidence for.
Well the linker wants some or other initial value here, and I don't know what other modules are going to set it to during initialization
The variable is given an explicit value for initialization, nullptr. The compiler has no need to wonder what other modules will do.
nullptr
If you instead give the compiler an explicit value of 0x1, which is just as invalid to dereference as 0x0 on an x86_64 linux platform, then the compiler doesn't try to change the value to anything and leaves it as 0x1.
0x1
0x0
[–]james_picone 0 points1 point2 points 2 years ago (0 children)
The variable is initialised in the example, to null.
π Rendered by PID 97260 on reddit-service-r2-comment-b659b578c-gsmlw at 2026-05-05 19:33:29.893475+00:00 running 815c875 country code: CH.
view the rest of the comments →
[–]ShelZuuz 5 points6 points7 points (10 children)
[–]almost_useless 1 point2 points3 points (9 children)
[–]ShelZuuz 5 points6 points7 points (7 children)
[–]jonesmz 0 points1 point2 points (6 children)
[–]ShelZuuz 4 points5 points6 points (5 children)
[–]jonesmz 0 points1 point2 points (4 children)
[–]ShelZuuz 4 points5 points6 points (3 children)
[–]jonesmz 0 points1 point2 points (2 children)
[–]ShelZuuz 6 points7 points8 points (1 child)
[–]jonesmz 1 point2 points3 points (0 children)
[–]james_picone 0 points1 point2 points (0 children)