Using std::print
with OpenMP results in a runtime error and I am not sure which path to take in resolving the issue. Consider the code below:
/// clang++ -fopenmp -std=c++23 -Wall -Wextra -Werror -g hello.cpp -o hello
#include <iostream>
#include <print> // C++23, not available in g++; use clang++
using namespace std;
int main(void) {
#pragma omp parallel
{
// cout << "Hello, world.\n"; // works fine
println("Hello, world"); // results in runtime error
}
#pragma omp critical
return 0;
}
If run the binary, I get:
dyld[65564]: weak-def symbol not found '__ZnwmSt19__type_descriptor_t'weak-def symbol not found '__ZnamSt19__type_descriptor_t'
Abort trap: 6
That translates to not finding:
$ echo __ZnwmSt19__type_descriptor_t | c++filt
operator new(unsigned long, std::__type_descriptor_t)
The same program runs fine if I comment out println
and uncomment the line that uses cout
:
$ clang++ -fopenmp -std=c++23 -Wall -Wextra -Werror -g hello.cpp -o hello
$ ./hello
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
The closest hint I got from googling is pointing at some explicit instantiation gone wrong (??)
I then looked into <print>
header file and I am unable to spot anything that stands out.
The last thing of interest is that the program size when using std::println
is much larger than with std::cout
. But the dynamic libraries that the program links to are the same.
# with std::cout
$ ls -lh ./hello
-rwxr-xr-x 1 stacker staff 42K Mar 31 18:05 ./hello
$ otool -L ./hello
./hello:
/opt/local/lib/libomp/libomp.dylib (compatibility version 5.0.0, current version 5.0.0)
@rpath/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.61.1)
# with std::println
$ ls -lh ./hello
-rwxr-xr-x 1 stacker staff 354K Mar 31 18:04 ./hello
$ otool -L ./hello
./hello:
/opt/local/lib/libomp/libomp.dylib (compatibility version 5.0.0, current version 5.0.0)
@rpath/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.61.1)
Short of moving back to using standard streams in a fairly large program, I am looking for thoughts and guidance on which way to go? i.e., go to the clang++
folks or the openmp
folks. The non-standard operator new
suggests to me that perhaps I should pursue this as an openmp
issue, but I am not sure.
Thoughts?
Adding clang++
information, and compilation without -fopenmp
:
# installed using macports
$ clang++ --version
clang version 17.0.6
Target: x86_64-apple-darwin23.3.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-17/bin
Without -fopenmp
option both cout
and println
work fine; note the openmp pragma
s are simply ignored without this option:
#include <iostream>
#include <print> // C++23, not available in g++; use clang++
using namespace std;
int main(void) {
#pragma omp parallel
{
cout << "Hello, world. (using cout)\n"; // works fine
println("Hello, world. (using println)"); // results in runtime error
}
#pragma omp critical
return 0;
}
$ clang++ -std=c++23 -Wall -Wextra -Werror -g hello.cpp -o hello
$ ./hello
Hello, world. (using cout)
Hello, world. (using println)
Update:
Happy to report that the issue is resolved with the latest libomp
, clang-18
, llvm-18
.
port installed llvm-18 clang-18 libomp
The following ports are currently installed:
clang-18 @18.1.7_0+analyzer (active)
libomp @18.1.6_0 (active)
llvm-18 @18.1.7_0 (active)
And compiling with -rpath
option to find the correct libc++.1.dylib on Mac.
clang++ -fopenmp -std=c++23 -Wall -Wextra -Werror -g hello.cpp -o hello -rpath /opt/local/libexec/llvm-18/lib
./hello
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
And here is the complete sample code for reference.
// clang++ -fopenmp -std=c++23 -Wall -Wextra -Werror -g hello.cpp -o hello -rpath /opt/local/libexec/llvm-18/lib
#include <print> // C++23, use clang++; not available in gcc13 and lower
using namespace std;
int main(void) {
#pragma omp parallel
{
println("Hello, world"); // works in clang-18!!!
}
#pragma omp critical
return 0;
}
C++ with OpenMP rules! Just give the process of open source some time to cook :-)