考虑以下使用的简单代码new(我知道没有delete[],但它与此问题无关):
int main()
{
int* mem = new int[100];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是否允许编译器优化new呼叫?
在我的研究中,g ++(5.2.0)和Visual Studio 2015不会优化new呼叫,而clang(3.0+)则可以.所有测试都是在启用完全优化的情况下进行的(-O3用于g ++和clang,用于Visual Studio的发布模式).
是不是new在引擎盖下进行系统调用,使编译器无法(并且非法)优化它?
编辑:我现在已经从程序中排除了未定义的行为:
#include <new>
int main()
{
int* mem = new (std::nothrow) int[100];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
#include <new>
int main()
{
int* mem = new (std::nothrow) int[1000];
if (mem != 0)
return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
事实证明,许多无辜的东西都是C++中未定义的行为.例如,一旦一个非空的指针已被delete"D 甚至在打印的是指针的值是未定义的行为.
现在内存泄漏肯定是坏事.但他们是什么类的情况 - 定义,未定义或其他类别的行为?
在他的演讲"效率与算法,性能与数据结构"中,Chandler Carruth谈到了在C++中需要更好的分配器模型.当前的分配器模型侵入了类型系统,因此很难在许多项目中工作.另一方面,Bloomberg分配器模型不会入侵类型系统,而是基于虚函数调用,这使得编译器无法"看到"分配并对其进行优化.在他的演讲中,他谈到编译器重复删除内存分配(1:06:47).
我花了一些时间来找到一些内存分配优化的例子,但我发现这个代码示例,在clang下编译,优化掉所有的内存分配,只返回1000000而不分配任何东西.
template<typename T>
T* create() { return new T(); }
int main() {
auto result = 0;
for (auto i = 0; i < 1000000; ++i) {
result += (create<int>() != nullptr);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
以下论文http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3664.html也说分配可以在编译器中融合,似乎表明一些编译器已经做了那种排序东西的.
由于我对高效内存分配的策略非常感兴趣,我真的很想理解为什么Chandler Carruth反对Bloomberg模型中的虚拟调用.上面的例子清楚地表明,clang可以在看到分配时优化.
是否有任何选项(/ O2除外)来改进Visual C++代码输出?在这方面,MSDN文档非常糟糕.请注意,我不是在询问项目范围的设置(链接时优化等).我只对这个特殊的例子感兴趣.
相当简单的C++ 11代码如下所示:
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4};
int sum = 0;
for(int i = 0; i < v.size(); i++) {
sum += v[i];
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
Clang的libc ++输出非常紧凑:
main: # @main
mov eax, 10
ret
Run Code Online (Sandbox Code Playgroud)
另一方面,Visual C++输出是一个多页面的混乱.我在这里遗漏了什么,还是VS真的很糟糕?
编译器资源管理器链接:https: //godbolt.org/g/GJYHjE
这应该每秒填充我的记忆大约100 MB.我用gnome-systemmonitor和htop跟踪内存.但不知怎的,它没有.为什么?
#include "unistd.h"
#include <iostream>
int main(int argc, char *argv[])
{
while (true){
std::cout << "New one" << std::endl;
new char[100000000];
sleep(1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
跑步:
g++ -std=c++11 -O0 main.cpp; ./a.out
Run Code Online (Sandbox Code Playgroud) 下面的代码显示了我的测试用例.我用clang ++ --std = c ++ 11 -O2和g ++ --std = c ++ 11 -O2编译了两者.
long long *ary = new long long[100000000]();
for (long long i = 0; i < 100000000; ++i)
ary[i] = i;
Run Code Online (Sandbox Code Playgroud)
std::vector<long long> vec(100000000, 0);
for (long long i = 0; i < 100000000; ++i)
vec[i] = i;
Run Code Online (Sandbox Code Playgroud)
对于我来说,我只进行了初始化测试,然后是初始化和for循环.结果如下:
GCC:
铛:
gcc结果与传统认为向量与数组一样快.而且,矢量的clang和gcc结果非常一致.然而,铿锵声的结果是荒谬的,阵列表现得相当快.任何人都知道为什么会这样?
c++ ×5
c++11 ×2
clang ×2
gcc ×2
memory ×2
optimization ×2
allocation ×1
arrays ×1
cl ×1
memory-leaks ×1
performance ×1
visual-c++ ×1