简体   繁体   中英

-O2 and -fPIC option in gcc

For performance optimization, I would like to make use of the reference of a string rather than its value. Depending on the compilation options, I obtain different results. The behavior is a bit unclear to me, and I do not know the actual gcc flag that causes that difference.

My code is

#include <string>
#include <iostream>

const std::string* test2(const std::string& in) {
   // Here I want to make use of the pointer &in
   // ...
   // it's returned only for demonstration purposes...
   return &in;
}

int main() {
   const std::string* t1 = test2("text");
   const std::string* t2 = test2("text");
   // only for demonstration, the cout is printed....
   std::cout<<"References are: "<<(t1==t2?"equivalent. ":"different. ")<<t1<<"\t"<<t2<<std::endl;
   return 0;
}

There are three compilation options:

gcc main.cc -o main -lstdc++ -O0 -fPIC && ./main 
gcc main.cc -o main -lstdc++ -O2 -fno-PIC && ./main 
gcc main.cc -o main -lstdc++ -O2 -fPIC && ./main 

The first two yield equivalent results ( References are: different. ), so the pointers are different, but the third one results in equivalent pointers ( References are: equivalent. ). Why does this happen, and which option do I have to add to the options -O2 -fPIC such that the pointers become again different? Since this code is embedded into a larger framework, I cannot drop the options -O2 or -fPIC .

Since I get the desired result with the option -O2 and also with -fPIC , but a different behavior if both flags are used together, the exact behavior of these flags is unclear to me.

I tried with gcc4.8 and gcc8.3.

Both t1 and t2 are dangling pointers, they point to a temporary std::string which is already destroyed. The temporary std::string is constructed from the string literal during each call to test2("text") and lives until the end of the full-expression (the ; ).

Their exact values depend on how the compiler (re-)uses stack space at a particular optimization level.

which option do I have to add to the options -O2 -fPIC such that the pointers become again different?

The code exhibits undefined behavior because it's illegal to compare invalid pointer values . Simply don't do this.

If we ignore the comparing part, then we end up with this version:

#include <string>
#include <iostream>

void test2(const std::string& in) {
   std::cout << "Address of in: " << (void*)&in << std::endl;
}

int main() {
   test2("text");
   test2("text");
}

Now this code is free from UB, and it will print either the same address or different addresses, depending on how the compiler re-uses stack space between function calls. There is no way to control this, but it's no problem because keeping track of addresses of temporaries is a bad idea to begin with.

You can try using const char* as the input argument instead, then no temporary will be created in a call test2("text") . But here again, whether or not two instances of "text" point to the same location is implementation-defined . Though GCC does coalesce identical string literals, so at least in GCC you should observe the behavior you're after.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM