How to catch undefined behaviour in function argument initialization

  • A+
Category:Languages

The following code works in clang++, but crashes spectacularly in g++

#include<vector> #include<iostream>  template<class Iterator> double abs_sum(double current_sum, Iterator it, Iterator it_end){     if (it == it_end)         return current_sum;     return abs_sum(current_sum+std::abs(*it),++it,it_end); }   int main(int argc, char** argv){     std::vector<double> values {1.0, 2.0,-5};      std::cout << abs_sum(0.0,values.begin(),values.end()) << std::endl;; } 

The culprit turns out to be this line:

return abs_sum(current_sum+std::abs(*it),++it,it_end); 

in clang, *it is evaluated before ++it, in g++ it's the reverse, causing the iterator to be increased before being dereferenced. It turns out that the order in which function arguments are evaluated is implementation defined.

My question is: How do I catch this type of error? Ideally I want to have an error or at least a warning when I'm accidentally depending on implementation specific details.

Neither clang nor gcc produces any warnings, even with -Wall.

 


My question is: How do I catch this type of error?

You don't. Undefined behaviour is undefined. You cannot catch it...

... but some tools could help you:

  • your compiler: all warnings enabled (g++/clang++ -Wall -Wextra -pedantic is a good start);
  • cppcheck;
  • clang-analizer;

They provide no guarantee though. This is why C++ is hard. You have (you, the coder) to know best and don't write UB. Good luck.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: