GCC无小的字符串优化
No small string optimization with gcc?
大多数std::string
实现(包括GCC)使用小字符串优化。例如。有一个讨论这个问题的答案。
今天,我决定检查我编译的代码中的字符串在什么点被移至堆。令我惊讶的是,我的测试代码似乎表明根本没有小组优化!
代码:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
int main(int argc, char* argv[]) {
std::string s;
cout << "capacity: " << s.capacity() << endl;
cout << (void*)s.c_str() << " | " << s << endl;
for (int i=0; i<33; ++i) {
s += 'a';
cout << (void*)s.c_str() << " | " << s << endl;
}
}
g++ test.cc && ./a.out
的输出是
capacity: 0
0x7fe405f6afb8 |
0x7b0c38 | a
0x7b0c68 | aa
0x7b0c38 | aaa
0x7b0c38 | aaaa
0x7b0c68 | aaaaa
0x7b0c68 | aaaaaa
0x7b0c68 | aaaaaaa
0x7b0c68 | aaaaaaaa
0x7b0c98 | aaaaaaaaa
0x7b0c98 | aaaaaaaaaa
0x7b0c98 | aaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0d28 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
我猜想较大的第一个指针,即0x7fe405f6afb8
是堆栈指针,而另一个指向堆。从第一个地址总是很大,而其他较小的地址则可以产生相同的结果,从而产生相同的结果。确切的值通常不同。较小的地址始终遵循2个分配方案的标准功率,例如0x7b0c38
列出了一次,然后列出了0x7b0c68
一次,然后列出了0x7b0c38
两次,然后0x7b0c68
4次,然后0x7b0c98
8次,等等。
阅读了霍华德的答案后,使用64位机器,我希望看到前22个字符印刷的相同地址,然后才能看到它的变化。
我错过了什么吗?
同样,有趣的是,如果我使用-O
编译(在任何级别上),在第一种情况下,我会得到一个恒定的小指针值0x6021f8
,而不是大价值,并且此0x6021f8
不会更改,无论我有多少次运行程序。
g++ -v
的输出:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/foo/bar/gcc-6.2.0/gcc/libexec/gcc/x86_64-redhat-linux/6.2.0/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../gcc-6.2.0/configure --prefix=/foo/bar/gcc-6.2.0/gcc --build=x86_64-redhat-linux --disable-multilib --enable-languages=c,c++,fortran --with-default-libstdcxx-abi=gcc4-compatible --enable-bootstrap --enable-threads=posix --with-long-double-128 --enable-long-long --enable-lto --enable-__cxa_atexit --enable-gnu-unique-object --with-system-zlib --enable-gold
Thread model: posix
gcc version 6.2.0 (GCC)
您的标志之一是:
--with-default-libstdcxx-abi=gcc4-compatible
和gcc4 dos 不支持小字符串优化。
GCC5开始支持它。ISOCPP状态:
默认使用小字符串优化而不是复制的参考计数。
支持我的主张。
此外,探索std :: string提及:
正如我们看到的 他们不利用小物体优化的感觉。
然后,当GCC5发挥作用时,他会更改上下文。
您可以检查C 11 ABI是否默认使用,如果您调用
gcc -v 2>&1 | sed -n 's/.*(--with-default-libstdcxx-abi=new).*/1/p'
如果您没有得到结果,则使用旧的ABI。(取自Conan Doku)
除了GSAMARAS给出的原因外,旧的ABI还用于较旧的redhat版本,这些版本与C 11 ABI不兼容:https://bugzilla.redhat.com/show_bug.cgi?id=1546704
- 小字符串优化(调试与发布模式)
- FBString 的小字符串优化是否依赖于未定义的行为?
- C++ C 样式字符串/字符数组的大小 - 优化
- strlen 是否针对字符串文字进行了优化?
- 字符串编码用于内存优化
- 添加字符时,编译器会停止优化未使用的字符串
- 短(ASCII,每个字符 7 位)字符串存储和C++中的比较优化
- 为什么C++编译器不在按值传递方案中优化更多的字符串构造?
- 通过从字符串IIN C 中删除垃圾字符来优化大小
- 优化弹性字符串文字解析
- C++按字符串调用函数,比较PHP的性能,如何在C++中优化代码
- C++小字符串优化 (SSO) 如何与容器配合使用?
- GCC无小的字符串优化
- 整数到字符串优化函数
- 优化c++代码以添加两个作为字符串的数字
- 想要优化此字符串操纵程序C
- 可靠地使用C++小字符串优化将短 std::字符串从文件转移到内存中
- 为什么在GCC 5.1中仍然启用COW std::字符串优化
- 小字符串优化(SSO)和移动语义
- c++ 11和c++ 03在支持std::string的小字符串优化方面有所不同