vs2015编译tcmalloc(gperftools2.4)

来源:互联网 发布:网络安全工程入门书籍 编辑:程序博客网 时间:2024/06/05 01:58

TcMalloc(Thread-CachingMalloc)是google-perftools工具中的一个内存管理库,所以一般提到tcmalloc,其实就是指使用gperftools,编译tcmalloc也就是编译gperftools。
第一次使用tcmalloc,网上找了好多关于使用tcmalloc的文章,都讲到了如何安装,如何使用,对于编译都是一笔带过。。。但是是真正实战的时候,发现如果对tcmalloc的代码结构不熟悉,这编译tcmalloc也是不小的坑。本文不涉及安装和使用,只根据自己今天的实际经历说说如何在在windows平台用msvc(准确地说是VS2015)编译tcmalloc。

下载

首先在官网下载gperftools,下载地址为:https://github.com/gperftools/gperftools ,
我下载的是最新的:gperftools-2.4.zip

哦,忘记说了,因为GFW的原因,google.com被挡了,如果你还不会翻墙,就无法去google官网下载gperftools,
参见下面的链接,我用文中提到的第一个也是最简单的QQ浏览器解决
分享几个目前可用的翻墙方法,解决Google、Facebook、Youtube及Twitter等被墙问题

如下图点击”Branch”出现下拉菜单在这里选择你要下载的版本:
这里写图片描述

编译报错

zip包下载解压后是如下图的文件结构:
这里写图片描述
此压缩包内含README_windows.txt说明文档,该文档包含详细使用教程。gperftools.sln则是MSVC工程文件,
根据gperftools源码包中的README_windows.txt说明,gperftools可以在VC++ 7.1(Visual Studio 2003)或以后的版本中运行。

You can load this solution file into VC++ 7.1 (Visual Studio 2003) or
later – in the latter case, it will automatically convert the files
to the latest format for you. (README_windows.txt中原文)

我现在用的VisualStudio 最新版本 visual studio 2015,所以应该是可以正常编译gperftools的,于是我用VS2015打开gperftools.sln,按提示将gperftools.sln转成了vs2015格式的。
这里写图片描述

然后按ctrl+shift+B编译整个工程。。。报出无数错误。。。

1>—— 已启动生成: 项目: libtcmalloc_minimal, 配置: Debug Win32 ——
2>—— 已启动生成: 项目: addressmap_unittest, 配置: Debug Win32 ——
3>—— 已启动生成: 项目: low_level_alloc_unittest, 配置: Debug Win32 ——
4>—— 已启动生成: 项目: tcmalloc_minimal_unittest-static, 配置: Debug Win32 ——
2> dynamic_annotations.c
1> dynamic_annotations.c
3> dynamic_annotations.c
4> dynamic_annotations.c
2>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
2> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
4>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
4> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
3>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
3> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
1>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
1> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
5>—— 已启动生成: 项目: addr2line-pdb, 配置: Debug Win32 ——
6>—— 已启动生成: 项目: nm-pdb, 配置: Debug Win32 ——
7>—— 已启动生成: 项目: tcmalloc_minimal_unittest, 配置: Debug Win32 ——
8>—— 已启动生成: 项目: tcmalloc_minimal_large_unittest, 配置: Debug Win32 ——
6> nm-pdb.c
5> addr2line-pdb.c
8> tcmalloc_large_unittest.cc
7> testutil.cc
6>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(1544): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧
6>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(3190): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧
6>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\nm-pdb.c(113): warning C4474: printf: 格式字符串中传递的参数太多
6> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\nm-pdb.c(113): note: placeholders and their parameters expect 1 variadic arguments, but 2 were provided
5>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(1544): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧
5>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(3190): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧
6>nm-pdb.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/SAFESEH”规范)
5>addr2line-pdb.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/SAFESEH”规范)
7>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
7> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
7> tcmalloc_unittest.cc
8>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): error C2371: “int8_t”: 重定义;不同的基类型
8> c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): note: 参见“int8_t”的声明
8>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
8> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
9>—— 已启动生成: 项目: frag_unittest, 配置: Debug Win32 ——
7>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
7> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
7>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
7> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
7> 正在生成代码…
9> frag_unittest.cc
9>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
9> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
9>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
9> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
10>—— 已启动生成: 项目: malloc_hook_test, 配置: Debug Win32 ——
11>—— 已启动生成: 项目: malloc_extension_test, 配置: Debug Win32 ——
10> testutil.cc
11> malloc_extension_test.cc
6> nm-pdb.vcxproj -> D:\os.package\cpp\gperftools\gperftools-2.4\Debug\nm-pdb.exe
12>—— 已启动生成: 项目: markidle_unittest, 配置: Debug Win32 ——
5> addr2line-pdb.vcxproj -> D:\os.package\cpp\gperftools\gperftools-2.4\Debug\addr2line-pdb.exe
13>—— 已启动生成: 项目: current_allocated_bytes_test, 配置: Debug Win32 ——
12> testutil.cc
10>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
11>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
10> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
11> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
10> malloc_hook_test.cc
11>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
11> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
12>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
12> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
12> markidle_unittest.cc
10>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
10> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
13> current_allocated_bytes_test.cc
10>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
14>—— 已启动生成: 项目: packed-cache_test, 配置: Debug Win32 ——
10> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
13>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
13> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
13>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
13> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
12>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
12> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
14> packed-cache_test.cc
12>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
12> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
10>c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\time.h(39): error C2011: “timespec”:“struct”类型重定义
10> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(440): note: 参见“timespec”的声明
10> 正在生成代码…
15>—— 已启动生成: 项目: pagemap_unittest, 配置: Debug Win32 ——
14>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
14> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
14>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
14> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
14>d:\os.package\cpp\gperftools\gperftools-2.4\src\packed-cache-inl.h(224): warning C4293: “<<”: Shift 计数为负或过大,其行为未定义
14> d:\os.package\cpp\gperftools\gperftools-2.4\src\tests\packed-cache_test.cc(38): note: 参见对正在编译的类 模板 实例化“PackedCache<64,uint64>”的引用
16>—— 已启动生成: 项目: page_heap_test, 配置: Debug Win32 ——
17>—— 已启动生成: 项目: realloc_unittest, 配置: Debug Win32 ——
17> realloc_unittest.cc
16> page_heap_test.cc
12> 正在生成代码…
15> pagemap_unittest.cc
15>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
15> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
15>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
15> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
18>—— 已启动生成: 项目: sampler_test, 配置: Debug Win32 ——
19>—— 已启动生成: 项目: stack_trace_table_test, 配置: Debug Win32 ——
17>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
17> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
17>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
17> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
16>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
16> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
18> sampler_test.cc
16>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
16> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
20>—— 已启动生成: 项目: thread_dealloc_unittest, 配置: Debug Win32 ——
21>—— 已跳过生成: 项目: preamble_patcher_test, 配置: Debug Win32 ——
21>没有为此解决方案配置选中要生成的项目
22>—— 已启动生成: 项目: system-alloc_unittest, 配置: Debug Win32 ——
18>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
18> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
18>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
18> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
20> thread_dealloc_unittest.cc
20>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
20> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
20>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型
20> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明
20> testutil.cc
20>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
20> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义
20> 正在生成代码…
========== 生成: 成功 2 个,失败 19 个,最新 0 个,跳过 1 个 ==========

修改config.h

看到上面的一大堆报错,脑子一下子就晕了,尼玛,什么玩意儿,编译器支持这么差?没有说明不支持vs编译器啊。
仔细分析上面的错误信息,发现主要就是snprintfint8_ttimespec重定义,

error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体
error C2371: “int8_t”: 重定义;不同的基类型
error C2011: “timespec”:“struct”类型重定义

考虑到vs2015比较新,用google搜索了一下”tcmalloc vs2010”,发现了这篇文章《TCMalloc static lib in vs2010》

文中解决的问题我并不关心,但我发现了这个:(#define WIN32_OVERRIDE_ALLOCATORS in config.h).
打开gperftools的源文件夹,在/src/windows下面果然发现找到了文中提到的config.h以及提到的宏定义WIN32_OVERRIDE_ALLOCATORS
这里写图片描述

这里写图片描述

我才明白,gpreftools为了能根据需要编译出不特性的代码,以及适应在不同版本的编译器下正常编译,设计了这个config.h通过宏定义来控制代码生成。在不同的编译器下编译,要根据编译报错的信息来相应修改config.h来解决。上图中最后一行,就是关于snprintf的

/* Define to 1 if your libc has a snprintf implementation */#undef HAVE_SNPRINTF

根据注释的说明,如果编译已经有snprintf 的实现,就要将HAVE_SNPRINTF定义为1

根据 www.cplusplus.com上关于snprintf的说明,snprintf是C++11支持的函数
VS2015版本已经有了snprintf的实现,所以要修改config.hHAVE_SNPRINTF的定义

/* Define to 1 if your libc has a snprintf implementation */#define HAVE_SNPRINTF 1

同样的道理,关于int8_t,也是因为int8_t所在的文件<stdint.h>已经是C++11的标准头文件,参见<cstdint> (stdint.h)

config.h中找到下面的定义

/* Define to 1 if you have the <stdint.h> header file. */#undef HAVE_STDINT_H

改为

/* Define to 1 if you have the <stdint.h> header file. */#define HAVE_STDINT_H 1

至于timespec也是因为定义在port.h中的timespec与c++标准头文件time.h中的timespec定义重复

这是port.h中的关于timespec的代码片段,看代码注释,是因为mingw没有定义timespc,而且mingw64中有定义,所以有点混乱,所以在这里用_TIMESPEC_DEFINED来做一个保护

// mingw64 seems to define timespec (though mingw.org mingw doesn't),// protected by the _TIMESPEC_DEFINED macro.#ifndef _TIMESPEC_DEFINEDstruct timespec {  int tv_sec;  int tv_nsec;};#endif

而在<time.h>是通过_CRT_NO_TIME_T来控制是否定义timespec

#ifndef _CRT_NO_TIME_T    struct timespec    {        time_t tv_sec;  // Seconds - >= 0        long   tv_nsec; // Nanoseconds - [0, 999999999]    };#endif

所以在config.h中加入下面一行,以去掉time.h中的timespec定义

#define _CRT_NO_TIME_T 1

最后保存config.h再编译,就可以通过了。

但是,编译通过只是第一步,是否能真的正常使用,还有待后面工作进行验证。

结论

要正确编译tcmalloc,应该根据c++编译器类型和版本的不同,修改config.h以达到与编译工具最匹配的状态,config.h中还有很多选项没有仔细研究,需要进一步深入了解。

1 0
原创粉丝点击