c++ - gcc 中的 -O2 和 -fPIC 选项
问题描述
为了性能优化,我想利用字符串的引用而不是它的值。根据编译选项,我得到不同的结果。这种行为对我来说有点不清楚,我不知道gcc
导致这种差异的实际标志。
我的代码是
#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 ∈
}
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;
}
共有三个编译选项:
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
前两个产生等效的结果 ( References are: different.
),因此指针不同,但第三个产生等效的指针 ( References are: equivalent.
)。为什么会发生这种情况,我必须将哪个选项添加到选项-O2 -fPIC
中以使指针再次变得不同?由于此代码嵌入到更大的框架中,因此我无法删除选项-O2
或-fPIC
.
由于我使用 option-O2
和获得了所需的结果-fPIC
,但是如果两个标志一起使用会出现不同的行为,因此我不清楚这些标志的确切行为。
我尝试使用 gcc4.8 和 gcc8.3。
解决方案
两者t1
和t2
都是悬空指针,它们指向一个std::string
已经被销毁的临时对象。临时std::string
是在每次调用期间从字符串文字构造的,test2("text")
并且一直存在到完整表达式(the ;
)的结尾。
它们的确切值取决于编译器如何(重新)在特定优化级别使用堆栈空间。
我必须将哪个选项添加到选项
-O2 -fPIC
中以使指针再次变得不同?
该代码表现出未定义的行为,因为比较无效指针值是非法的。根本不要这样做。
如果我们忽略比较部分,那么我们最终会得到这个版本:
#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");
}
现在这段代码从 UB 中解放出来了,它将打印相同的地址或不同的地址,这取决于编译器如何在函数调用之间重用堆栈空间。没有办法控制这一点,但这没问题,因为一开始就跟踪临时人员的地址是一个坏主意。
您可以尝试使用const char*
作为输入参数,然后在 call 中不会创建临时参数test2("text")
。但是在这里,两个实例是否"text"
指向同一个位置是实现定义的。尽管 GCC 确实合并了相同的字符串文字,但至少在 GCC 中你应该观察你所追求的行为。
推荐阅读
- c - strlen 在循环中给出分段错误
- python - 如何设置可检查的菜单设置,真或假?如果是真的做某事
- itext - 使用 itextsharp 识别眼睛看不见但可以使用 Acrobat 搜索的文本
- apache-spark - 将 Parquet 文件加载到 HDFS 表中-Pyspark
- c# - 如何使用 C# Steeltoe 库连接到现有的 ZUUL 服务器?
- azure - 有没有办法根据带有 Runbook/自动化脚本的标签删除资源组?
- webpack - 未找到块列表 Webpack 插件
- flow-project - How is FLOW currently dealing with clipping actions, squash_to_range, no_final_linear
- html - 无法更改 Angular 材质输入占位符的文本颜色
- python - Python:如果元素是另一个嵌套列表中的元素,则删除嵌套列表中的重复元素