Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

jjimenezshaw
Copy link
Contributor

Discussed at https://lists.osgeo.org/pipermail/proj/2025-May/011851.html

The bug happens only in NetBSD

Does not apply to master because that code was refactored in #4446

  • Added clear title that can be used to generate release notes

@rouault rouault changed the title [fix] use std::abs instead of abs for NetBSD [9.6 branch] [fix] use std::abs instead of abs for NetBSD May 5, 2025
@rouault rouault added this to the 9.6.1 milestone May 5, 2025
@gdt
Copy link
Contributor

gdt commented May 5, 2025

Looking at the commit, it matches what I tested.

latitudes.cpp includes <math.h> which declares the C functions. My understanding is that C++ practice is to include <cmath> instead. Plus, abs(3) is defined in stdlib.h and not math.h, it seems.

https://pubs.opengroup.org/onlinepubs/9799919799/functions/abs.html
https://pubs.opengroup.org/onlinepubs/9799919799/functions/fabs.html

Do people understand why bare abs resolves to std::abs on other systems? Is this a particular choice within undefined behavior? I'm asking because I wonder if more UB is lurking.

@rouault
Copy link
Member

rouault commented May 5, 2025

Do people understand why bare abs resolves to std::abs on other systems?

I found this post https://stackoverflow.com/questions/21392627/abs-vs-stdabs-what-does-the-reference-say : "According to the cplusplus.com website, abs is supposed to behave differently for the stdlib.h C version, if you include "

and trying with abs.cpp :

#include <cmath>

double foo(double x)
{
    return abs(x);
}
$ g++ -E abs.cpp 
[...]
extern "C++"
{
namespace std __attribute__ ((__visibility__ ("default")))
{
  using ::abs;
[...]
# 70 "/usr/include/c++/9/bits/std_abs.h" 3
  inline constexpr double
  abs(double __x)
  { return __builtin_fabs(__x); }
[...]

And actually the minimum reproducer is:

extern "C"
{
extern int abs (int __x) throw () __attribute__ ((__const__)) ;
}

extern "C++"
{
namespace std __attribute__ ((__visibility__ ("default")))
{
  inline constexpr double
  abs(double __x)
  { return __builtin_fabs(__x); }
}
}

double foo(double x)
{
    return abs(x);
}

@gdt I suspect your system doesn't properly implement "Since C++11, additional overloads are provided in this header () for the integral types: These overloads effectively cast x to a double before calculations"

@rouault rouault merged commit 74d1e57 into OSGeo:9.6 May 5, 2025
27 checks passed
@gdt
Copy link
Contributor

gdt commented May 5, 2025

Thanks. I'll look into that. It seems the answer on stackexchange says that at least cppreference.com isn't reliable, and that for portable code the best practice is to include cmath and then use std:: prefixes for the functions, to avoid all the issues for which people can't seem to quite agree on what the standard says.

It looks like proj_internal.h includes cmath,despite being .h and not .hpp, and also that a number of source files don't include it, but I'm not sure I follow.

There are a large number of cpp files in proj source that include math.h. But some of them are using fabs() which is the other portable approach, e.g. projections/tmerc.cpp.

It seems our practice is to add std:: when missing, ending up being defensive/portable and staying away from the sharp edges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants