#how do you check if a function has side effects?

97 messages · Page 1 of 1 (latest)

wide mauve
#

a.k.a.


void runThing()
{
  std::cout<<__FUNCTION__<<std::endl;
}

void sample()
{
  while(true) {
    runThing();
  }
}

int main()
{
  static_assert(func_has_side_effects<decltype(runThing)>::value);
}

to make sure that the infinite loop here does NOT cause UB?

pure lichenBOT
#

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.

wide mauve
#

(since C++11)

fickle iron
#

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

wide mauve
fickle iron
#

Why do you think the compiler has a way of knowing?

wide mauve
#

it is obvious the compiler knows

fickle iron
#

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

limber schooner
wide mauve
#

for each object file

limber schooner
#

LTO does all kinds of optimisation

wide mauve
limber schooner
#

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

wide mauve
limber schooner
#

It's not the linker detecting it

#

In LTO the linker calls back to the compiler again with pre-processed IR

wide mauve
limber schooner
#

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

wide mauve
limber schooner
#

you cannot

#

(automatically)

#

use documentation to do it, or otherwise just make the loop safe yourself

wide mauve
#

increment a global counter and print that counter in a file descriptor when main finishes?

limber schooner
#

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)

wide mauve
barren tangle
#

Read the documentation

wide mauve
# limber schooner .

in the C++ language, which expressions are considered as side effects?
system calls?
main's return statement?

limber schooner
#

also btw, please don't ping me on literally every single message 😛

wide mauve
#
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?

fickle iron
#

that wound't be a confirming implmentation of those library functions

wide mauve
fickle iron
#

the standard has requirements for those functions, you can't just ignore that and declare it's fine

gilded quiver
#

And not break your loop

wide mauve
barren tangle
#

What are you actually trying to do here?

wide mauve
limber schooner
limber schooner
#

memory-mapped I/O

wide mauve
#

ohhhhhhhhhh

#

memory managed input output operations

#

(haven't done that... yet)

barren tangle
wide mauve
#

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

pure lichenBOT
#

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

limber schooner
wide mauve
limber schooner
#

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

wide mauve
limber schooner
#

I/O means interacting with the outside world

wide mauve
#

or some firmware writing/reading primitive

limber schooner
#

that can be flicking a switch, reading the current temperature, setting off a bomb, catching fire, whatever

wide mauve
#

^ so like, read some sensor's readings, sleep 1 sec, repeat infinitely, if sensor value is, something, then run code???

#

okayyyyyyyy

#

so

limber schooner
#

yeah, that's one common example

barren tangle
#

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

wide mauve
#
#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

wide mauve
limber schooner
#

if targetting recent compilers (i.e. specifically not older clang), just while (true) {} is a safe way to run infinitely

wide mauve
gilded quiver
limber schooner
#

since C++98, but was introduced in 2023 or w/e

#

compilers other than Clang already behaved like that in practice

wide mauve
#

no idea which compilers implemented that funky safe infintie loop

#

!solved

pure lichenBOT
hot monolith
#

basically all compilers other than clang < 19 behaved well with the empty loop already

#

like wreien said

wide mauve
#

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++

wide mauve
#

byeeeeeeee

wide mauve