#how do you check if a function has side effects?
97 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
(since C++11)
It's up to the author of runThing to know if the loop has side effects or not, there isn't a way to test for it
I don't believe that, the compiler has some way of knowing this at compile time, so there must be a way to write a trait
Why do you think the compiler has a way of knowing?
it is obvious the compiler knows
If the definition is inline the compiler can see it, but only if its inline
if it's not inline, then the call to the function should be emitted and so it's not an empty loop
if the definition is inline, you can see for yourself
and even if the compiler can tell, the standard does not offer a way for the compiler to tell you
The compiler may not know in time though; consider eg LTO
wasn't that used to clean up unused functions produced in compiled object files? what I am asking is known during the compilation phase, we don't care about the linker
for each object file
LTO does all kinds of optimisation
and?
runThing may be defined in a different object file, or call functions defined elsewhere
At the time you call it, the compiler does not know whether it will have side effects
At link time, when it has the definition, it may be able to determine that
But you've already ended "regular compilation" in which a type trait would work
This happens already with things like detection of gnu::pure, which is effectively what you're asking for
okay, so the compilation phase cannot introspect foreign object files,
and what can the linker detect?
It's not the linker detecting it
In LTO the linker calls back to the compiler again with pre-processed IR
that's to force some function to have no side effects, that's not what I am looking for
You misunderstand
Detection of pure is the compiler detected that it had no side effects and "remembered" that by marking it pure automatically for the sake of later optimisations
so then how are humans supposed to see that a function is safe to use in an infinite loop?
you cannot
(automatically)
use documentation to do it, or otherwise just make the loop safe yourself
tell me the manual solution
increment a global counter and print that counter in a file descriptor when main finishes?
main will never finish if you have an infinite loop somewhere
that's kinda the point
(and having unterminated threads at the point of main finishing, if that's what you mean, is also UB so you're not gaining anything there)
so... about that manual solution, what is it?
.
Read the documentation
in the C++ language, which expressions are considered as side effects?
system calls?
main's return statement?
void runThing()
{
}
volatile int num = 0;
void sample()
{
while(true) {
runThing();
int num1 = num;
}
}
int main()
{
sample();
}
so according to the standard, if I read from a volatile, this is a side effect,
so sample() should have no UB,
is this really true?
calling a library I/O function
...and if I overwrite puts, or printf to have an empty body and some hardcoded return value, does the function still cause side effects?
that wound't be a confirming implmentation of those library functions
yes it would be, when using a custom made libc++ implementation for embedded devices
the standard has requirements for those functions, you can't just ignore that and declare it's fine
If the compiler isn't sure, it will just assume there are side effects
And not break your loop
what about this
#1373636166087344209 message
What are you actually trying to do here?
to write a helper function that halts the program, and spins the while loop infinitely, kinda like a gdb breakpoint
Yes; because num could be e.g. an MMIO'd value where if you read from it 50 times it'll terminate your program
what is MMIO ?
memory-mapped I/O
If you want to literally just spin in a while loop you can write a trivial loop (since 23/26 can't remember exactly)
so that's the fix, we don't bother checking for functions' side effects, we just slap a volatile variable reading, and voala
it is safe
!solved
Thank you and let us know if you have any more questions!
This thread is now set to auto-hide after an hour of inactivity
yeah, since C++26 (and as a DR, so even in older standard modes for recent enough compilers)
wait... there are separate counters that track how many times some memory mapped fundamental type variable was read? and they can decide to run code based on that???
there can be, sure
MMIO can do whatever you like, it's I/O
I have worked on embedded systems where there was a register that incremented a counter every time you read from it, for instance
for me, Input/Output means, the sytem calls write/read/recv/send
I/O means interacting with the outside world
or some firmware writing/reading primitive
that can be flicking a switch, reading the current temperature, setting off a bomb, catching fire, whatever
^ so like, read some sensor's readings, sleep 1 sec, repeat infinitely, if sensor value is, something, then run code???
okayyyyyyyy
so
yeah, that's one common example
Think of it a bit like writing to a file on a UNIX system, it doesn't really have to just be a file, could be /dev/null or something
#ifdef __cplusplus
volatile int num = 20;
#endif
void runInfinitely()
{
whle(1)
{
#ifdef __cplusplus
int num2 = ::num;
#endif
}
}
this here, to be compatible with C and C++, should be a safe way to run infinitely
...which means that the compiler must bruteforce each system call that exists, and know in advance which ones are side effects...
if targetting recent compilers (i.e. specifically not older clang), just while (true) {} is a safe way to run infinitely
you mean that funny C++ standard proposal to allow infinite loops to be safe since C++26?

I'm late, but yes, this looks legal
since C++98, but was introduced in 2023 or w/e
compilers other than Clang already behaved like that in practice
too risky man, I will stick with the volatile
no idea which compilers implemented that funky safe infintie loop
!solved
Message is already solved
basically all compilers other than clang < 19 behaved well with the empty loop already
like wreien said
hell,
there was a C++ standard proposal for the while loop,
and they were showcasing how this can cause normal rust code to fail to compile, because LLVM's internals were writing a infinite loop in C++
oh yeah btw,
in std::atomic's rule of 5 functions, and actually a few other functions too, I keep seeing volatile being used, but I have no clue why
maybe I will re-ask here after a few months after I read some more Linux docs
byeeeeeeee
can I put num as a local variable before the while loop?