问题
My team is writting code to be compiled for both Windows (using VS2015
) and Android (using GCC 4.9
invoked by QtCreator
).
We figured out that Android binaries had a problem with abs
function.
double a = 1.0;
double b = 0.5;
std::cout << abs( a - b ) << std::endl;
std::cout << std::abs( a - b ) << std::endl;
Displays:
1
0.5
This is a known issue, found this topic (among others): Strange bug in usage of abs() I encountered recently
There are lots of places where we use abs
, I'll replace them all by std::abs
. Fine. But how can I prevent abs
to be used again in the future?
Found this topic: Avoiding compiler issues with abs(), but it did not help.
I can't enable treating all warnings as errors (-Werror -Wall) because g++ is much less permissive than MSVC. Even if we make the effort to compile with 0 warning on MSVC, we still get tons of them with g++ (among them there could be one about abs being used badly) and we historically ignore them. Fixing them all would take us too much effort.
回答1:
Do you have a header file that is basically included by everything? Some kind of holder-of-all-fundamentals? If so, you can put this in there:
extern void NeverDefined();
inline int abs(int a) {
NeverDefined();
return a;
} // abs(int)
If you then get a linker error on NeverDefined
, you'll know there's a problem!
Normally I simply wouldn't define the function in question, but since it's a library function I had to have this second level.
Edit
In fact: don't bother with a header file (the standard definition will suffice). Write your own abs.cc
with the above code (no inline
) and it will supersede the library definition.
Of course, this won't work if the original file marks the function inline
- in which case you could always edit the original definition...
回答2:
Do you have the possibility to set mandatory Compiler flags at a central Location (common cmake includes or whatever other build system you use)? If so, you can create a header file as indicated by John and add a compile flag that will include the file at the beginning of any compilation unit:
MSVC: /FI <path_to_file>
GCC: -include <path_to_file>
Clang: Same as GCC
回答3:
As suggested in the same linked answer from your question:
<math.h>
is responsible forabs(int)
<cmath>
is responsible forstd::abs(double)
If you have a top-most header file then simply put below method:
template<typename T> void abs (T);
Hence, wherever there is an abs
found, a compiler error will be reported for its void
as return value. Additionally this function is unimplemented to give a linker error at least.
This compiler error can be used for replacing such abs()
with std::abs()
. For harmless abs(int)
, this will expectedly not generate any error as it's available in <math.h>
.
Suppose, you don't have any header file included in all the source files then as a one time exercise, you may want to replace every text of #include<math.h>
with #include<cmath>
. However, this won't be full proof in all cases. For example:
double my_abs () {
using std::abs;
return abs(x - y);
}
Hence, it's good to have a common utility header file in all the source file as a practice. Let it be empty.
来源:https://stackoverflow.com/questions/38499142/c-how-can-i-prevent-my-team-developers-from-using-integer-version-of-abs-by-mi