typeid(T).name() 方法在 linux 下通过 g++ 编译得不到正确的类型

说实话,我不是 c++ 程序员,之前虽然出于个人兴趣研究过 c++,也跟风看过《c++ primer》。

但是要说水平,我估计还没入门吧。

要不是之前苦学过一段时间的 c,估计连基本的语法也一知半解了。

最近在研究 nodejs,当然不是研究 nodejs 常用的 api 怎么用,如果只是仅仅止步于此的话,根本用不着接触到 c++ 了。

我们知道,nodejs 是用 c++ 写的,而且 nodejs 本身是由 v8 引擎强力驱动的。因此,如果想在 nodejs 上更进一步,知其然更知其所以然的话,研究下 nodejs 的源码是必不可少的。

这里说研究二字,或许有点夸张了,更好的说法应该是开始学习吧。

刚开始其实是碰到 c++ 模板的代码,看的云里雾里的。因为好久没接触过 c++ 了,因此咋一看,愣是没太看懂表示的啥意思。

于是就只能开始上网搜几个示例,自己写写练练手嘛。

哪知道碰到下面这个示例:

#include <iostream>
#include <string>
#include <type_traits>
#include <typeinfo>

using namespace std;

template<typename T>
void printType(const T& t){
  cout << typeid(T).name() << endl;
}

int main(int argc, char* argv[]) {
  const string t("test");

  printType(&t);

  return 0;
}

这个 typeid 以前还真是从来没用过,后来一查 c++ 文档 ,才明白这个方法是获取变量类型的,就跟 JavaScript 里面的 typeof 有点类似。

这明显有 api 可以查的问题都算不得问题,问题是,当我在编译运行的时候,却遇到了令我困惑的地方了。

很明显,我是在 linux 系统中,动用 g++ 进行编译的

$ g++ test.cc
$ ./a.out
PKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

但是输出的结果,好像不是我想要看到的内容啊,简直跟乱码一样。

于是我又改了改代码,干脆改成这样测试下:

#include <iostream>
#include <string>
#include <type_traits>
#include <typeinfo>

using namespace std;

int main(int argc, char* argv[]) {
  cout << typeid(int).name() << endl;
  cout << typeid(string).name() << endl;
  
  return 0;
}

但是依旧是乱码

$ g++ test.cc
$ ./a.out
i
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

心想,这是什么鬼,为什么跟文档不一样。

于是,只得开始找原因了。

经过漫长的搜寻查找以后,终于功夫不负有心人,在 stackoverflow 上找到了这个问题的解决方案:https://stackoverflow.com/questions/789402/typeid-returns-extra-characters-in-g?r=SearchResults#

大意就是说,这是 gcc 编译器的问题,编译出来得到的结果 mangled 了,这个词可以理解为“混乱”或者“错位”的意思,因此必须要用 c++filt 程序 unmangled 回去。

但是这个 c++filt 是个什么东西呢?

姑且先不管,先试试看有没有效果吧。

$ ./a.out | c++filt -t
int
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >

可以看到,用管道符这么一转换,果然得到了想要的结果。

但是这个 c++filt 究竟是个什么程序呢?

这个时候,熟悉 Linux 的各位肯定能想到,我就 man 一下嘛,自然能找到得想要的答案吧。

那我们就 man 一下吧。

C++FILT(1)                           GNU Development Tools                           C++FILT(1)

NAME
       c++filt - Demangle C++ and Java symbols.

SYNOPSIS
       c++filt [-_|--strip-underscore]
               [-n|--no-strip-underscore]
               [-p|--no-params]
               [-t|--types]
               [-i|--no-verbose]
               [-s format|--format=format]
               [--help]  [--version]  [symbol...]

DESCRIPTION
       The C++ and Java languages provide function overloading, which means that you can write
       many functions with the same name, providing that each function takes parameters of
       different types.  In order to be able to distinguish these similarly named functions C++
       and Java encode them into a low-level assembler name which uniquely identifies each
       different version.  This process is known as mangling. The c++filt [1] program does the
       inverse mapping: it decodes (demangles) low-level names into user-level names so that
       they can be read.
       
       .....

由于篇幅有限,这里就不全贴出来了,我们从 description 中可以看到,这个程序主要用于解码低等级的名称,解码为用户可阅读的名称,之所以要这么做,是因为 c++ 中的重载特性所决定的。

但是这个程序很有意思的地方是,它不仅仅能解码类型,还能给字符解码:

$ c++filt -n _Z1fv
f()

所以看到这里,你就该明白了,这个 c++filt 相当于是个解码的玩意儿,因为本身代码是 gcc 编译的,为了优化编译开销,给这个地方进行了编码,因此想要阅读,必须要用这个程序解码回来才行。

不过如果不是有经验的程序员来指点迷津,寻常人哪里知道这个地方这种弯弯绕绕呢?

本来觉得这地方挺简单的,好像没有必要记录下来。

但是后来一想,有时候,我们碰到过的坑,花时间记录下来,即使在之后的日子里一直无人问津,但是谁知道,会不会有一天有某些人能够从中获取到哪怕一丝丝灵感呢。

我想,哪怕只是抱着这么个美好的愿景,去做这么一件事,那也是一件极好的事情吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容