So basically I am trying to set an environment variable in my C++ code to force the number of threads to be 1. I am using multiple machine learning libraries which by default use OpenMP
and can be forced to operate in single thread mode by setting the following environment variable: OMP_NUM_THREADS=1
Here's my issue. I want to set this environment variable from within a library I am building.
When I set the environment variable from my main function (executable linking against the library I am building) then it works as expected (only 1 thread is used during the execution of the program):
auto implPtr = FRVT_11::Interface::getImplementation();
implPtr->initialize(CONFIG_DIR);
char ompEnv[]="OMP_NUM_THREADS=1";
putenv( ompEnv );
// More code
However, if I try to set the environment variable from within the library I am building (for example from within the getImplementation
function), then the number of threads used is 4 instead of 1:
// This does not work
std::shared_ptr<FRVT_11::Interface> FRVT_11::Interface::getImplementation() {
char ompEnv[]="OMP_NUM_THREADS=1";
putenv( ompEnv );
return std::make_shared<MyImplementation>();
}
Any ideas why this would be the case? I am building and shipping the library so I need the number of threads to be set from within the library.
Your "library function" version is undefined behavior.
Your "main function" version is also likely undefined behavior, as an extra bonus, but you aren't aware of it, yet.
From the Linux version of the putenv(3)
manual page (other OS implementations are likely the same):
The string pointed to by [the parameter to putenv()] becomes part of the environment, so altering the string changes the environment.
That's your big, honking, alarm bell: you better not even think of touching this string, ever again, even with a 10-foot pole, because it is now a part of the environment.
In your shared library version:
char ompEnv[]="OMP_NUM_THREADS=1";
This array is a local variable in the function. Therefore, this array gets destroyed when this function returns. But this array is also passed as a parameter to putenv()
. Grand total: as soon as this function returns, one of your environment variables is now a dangling pointer.
There is no sufficient information to conclusively prove that your "main function" version is also undefined behavior, but it's highly likely, too.