首页 > 编程语言 >C++拾趣——转换编译器生成的类型名为代码中的类型名

C++拾趣——转换编译器生成的类型名为代码中的类型名

时间:2024-08-25 15:51:47浏览次数:13  
标签:__ std Sp C++ 编译器 类型 shared 拾趣

大纲

在软件开发中,特别是在使用C++这类静态类型语言时,编译器在编译过程中会生成许多内部表示,包括类型信息。这些内部类型名通常用于编译器的内部处理,比如类型检查、优化和代码生成等。
在这里插入图片描述

然而,在编写源代码或进行调试时,我们更习惯于使用人类可读和易于理解的类型名。比如我们不太能看懂_ZSt10_ConstructIN11composition6TalkerEJRN6rclcpp11NodeOptionsEEEvPT_DpOT0_,但是可以看懂void std::_Construct<composition::Talker, rclcpp::NodeOptions&>(composition::Talker*, rclcpp::NodeOptions&)

因此,将C++编译器生成的类型名转换成代码中的类型名具有多方面的必要性:

  • 提高代码的可读性。源代码中的类型名应该清晰地反映其意图和用途,以便于开发者和维护者理解。编译器生成的类型名往往包含编译器特有的前缀、后缀或编码,这使得它们难以被人类直接理解。通过转换成代码中的类型名,可以大大提高代码的可读性和可维护性。

  • 促进团队合作。在团队开发环境中,不同的开发者可能使用不同的编译器或编译器版本。如果直接使用编译器生成的类型名,可能会导致类型名在不同环境下不一致,进而增加团队合作的难度。而将类型名转换为代码中定义的类型名,可以确保所有开发者在查看和理解代码时使用的是相同的类型名,从而降低沟通成本和错误率。

  • 简化调试过程。在调试过程中,开发者经常需要查看变量的类型和值。如果变量使用的是编译器生成的类型名,那么在调试器中查找和识别这些类型可能会变得困难。而将类型名转换为代码中定义的类型名,可以使调试过程更加直观和高效。

下面我们将通过代码编写一个工具,负责将这些编译器生成的类型名转换成代码中的类型名。

代码

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#include <memory>
#include <vector>

// 辅助函数:解码类型名
std::string demangle(const char* name) {
    int status = 0;
    char* demangled = abi::__cxa_demangle(name, nullptr, nullptr, &status);
    std::string result = (status == 0) ? demangled : name;
    free(demangled);
    return result;
}

int main(int argc, char* argv[]) {
    for (int i = 1; i < argc; ++i) {
        std::cout << "argv[" << i << "]" << std::endl << argv[i] << " -> " << demangle(argv[i]) << std::endl << std::endl;
    }
    return 0;
}

测试

我们输入《Robot Operating System——深度解析通过符号和隐式加载动态库的运行模式》一文中追踪的符号。

./build/DemangleExample _ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE ZSt10_ConstructIN11composition6TalkerEJRN6rclcpp11NodeOptionsEEEvPT_DpOT0 ZNSt23_Sp_counted_ptr_inplaceIN11composition6TalkerESaIvELN9__gnu_cxx12_Lock_policyE2EEC1IJRN6rclcpp11NodeOptionsEEEES2_DpOT ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE2EEC1IN11composition6TalkerESaIvEJRN6rclcpp11NodeOptionsEEEERPT_St20_Sp_alloc_shared_tagIT0_EDpOT1 ZNSt12__shared_ptrIN11composition6TalkerELN9__gnu_cxx12_Lock_policyE2EEC1ISaIvEJRN6rclcpp11NodeOptionsEEEESt20_Sp_alloc_shared_tagIT_EDpOT0 ZNSt10shared_ptrIN11composition6TalkerEEC1ISaIvEJRN6rclcpp11NodeOptionsEEEESt20_Sp_alloc_shared_tagIT_EDpOT0

然后我们会看到如下结果

From
_ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE
To:
composition::Talker::Talker(rclcpp::NodeOptions const&)

From
ZSt10_ConstructIN11composition6TalkerEJRN6rclcpp11NodeOptionsEEEvPT_DpOT0
To:
void std::_Construct<composition::Talker, rclcpp::NodeOptions&>(composition::Talker*, rclcpp::NodeOptions&)

From
ZNSt23_Sp_counted_ptr_inplaceIN11composition6TalkerESaIvELN9__gnu_cxx12_Lock_policyE2EEC1IJRN6rclcpp11NodeOptionsEEEES2_DpOT
To:
std::_Sp_counted_ptr_inplace<composition::Talker, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplacerclcpp::NodeOptions&(std::allocator<void>, rclcpp::NodeOptions&)

From
ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE2EEC1IN11composition6TalkerESaIvEJRN6rclcpp11NodeOptionsEEEERPT_St20_Sp_alloc_shared_tagIT0_EDpOT1
To:
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<composition::Talker, std::allocator<void>, rclcpp::NodeOptions&>(composition::Talker*&, std::_Sp_alloc_shared_tag<std::allocator<void> >, rclcpp::NodeOptions&)

From
ZNSt12__shared_ptrIN11composition6TalkerELN9__gnu_cxx12_Lock_policyE2EEC1ISaIvEJRN6rclcpp11NodeOptionsEEEESt20_Sp_alloc_shared_tagIT_EDpOT0
To:
std::__shared_ptr<composition::Talker, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, rclcpp::NodeOptions&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, rclcpp::NodeOptions&)

From
ZNSt10shared_ptrIN11composition6TalkerEEC1ISaIvEJRN6rclcpp11NodeOptionsEEEESt20_Sp_alloc_shared_tagIT_EDpOT0
To:
std::shared_ptr<composition::Talker>::shared_ptr<std::allocator<void>, rclcpp::NodeOptions&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, rclcpp::NodeOptions&)

这样整个符号就容易理解了。

代码地址

https://github.com/f304646673/cpulsplus/tree/master/demangled

标签:__,std,Sp,C++,编译器,类型,shared,拾趣
From: https://blog.csdn.net/breaksoftware/article/details/140900155

相关文章

  • C++函数调用栈从何而来
    竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~个人主页:rainInSunny | 个人专栏:C++那些事儿、Qt那些事儿目录写在前面原理综述x86架构函数调用栈分析如何获取rbp寄存器的值总结写在前面  程序员对函数调用栈是再熟悉不过了,无论是使用IDE调试还是GDB等工具进行调试,都离......
  • C++函数调用栈从何而来
    竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~个人主页:rainInSunny | 个人专栏:C++那些事儿、Qt那些事儿文章目录写在前面原理综述x86架构函数调用栈分析如何获取rbp寄存器的值总结写在前面  程序员对函数调用栈是再熟悉不过了,无论是使用IDE调试还是GDB......
  • 【C++ 面试 - 内存管理】每日 3 题(一)
     ✍个人博客:Pandaconda-CSDN博客......
  • C++多态——虚函数
    其实在学习的时候,一直没有搞懂为什么要用虚函数,为什么需要传递基类的引用或者指针,要用谁的时候写谁不就好了。其实这时候我的思维还局限在面向过程编程,不是面向对象编程。现在搞明白了,因为多态,利用继承的思想,减少代码复用。我们来看下面的例子。#include<iostream>usingnamesp......
  • C++/python趣味实验之:互动游戏
    之前,我们已经使用python做出了可以根据C++数据变更的血条现在,拓展一下这个程序,制作一个可以互动的游戏既然是游戏,那就需要一个启动界面,所以我们可以制作一个蓝天白云的场景怎么实现呢?首先,我们要明白,这只是一个启动界面,所以一定是根据C++方面的数据而启动和关闭的,这时,就需要......
  • C++(asctime()、ctime())
    目录1.asctime()2.ctime()3.区别3.1示例对比4.总结在C++中,asctime()和ctime()都是用于将时间转换为可读字符串的函数,但它们有一些细微的区别。1.asctime()作用:asctime()函数将structtm类型的时间结构转换为字符串。这个函数通常与localtime()或gmtime()......
  • win10系统c++与opencv 依赖环境配置
    一、VSC++配置opencv库1、下载opencv(https://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.3.0/)2、在官网下载opencv3.3.0.exe文件然后解压到D盘D:\opencv3、配置系统环境:①添加环境变量:控制面板-系统-高级系统设置-环境变量-系统变量Path中添加下......
  • C/C++语言基础--结构体知识详解(包括:结构体数组、字节对齐、位段等内容)
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言C语言地结构体是核心内容之一,他运行自定义数据类型,可以将不同地数据类型当作成一个整体,变成一个数据类型,运用及其广泛欢迎点赞+收藏+关注,本人将会持续更新加粗样式文章目录结构体结构体是什么?结构体的申......
  • C++(std::cout 处理 char*)
    目录1.std::cout和char*2.std::cout处理nullptr情况3.数组与指针的区别4.特殊字符的处理5.总结在C++中,std::cout是标准输出流,通常用于将数据输出到控制台。在处理char*类型时,std::cout的行为与处理其他类型有所不同。1.std::cout和char*char*是一个指向字......
  • 突破编程:C++中的组合模式(Composite Pattern)
    突破编程:C++中的组合模式(CompositePattern)在软件设计领域,组合模式(CompositePattern)是一种结构型设计模式,它允许你将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式让客户端代码可以一致地处理单个对象和组合对象,无需关心对象的具体类型,从而简化了客户端代码......