[√]leak tracer的stack address始终无法被addr2line识别

简介: [√]leak tracer的stack address始终无法被addr2line识别

感谢文章:blog.csdn.net/tq08g2z/art…

使用适配过Android的leak tracer,不要使用官方的。我自己写的测试demo

注意

尽量将leak tracer编译到要检测内存泄露模块的动态库中,不要单独将leak tracer编译为一个so动态库,否则会导致addr2line无法正确识别出地址符号。

LeakTracer使用教程

在Android平台上检测内存泄露,最终选择使用leak tracer。

通过leak traker,收集到leak结果如下:

# LeakTracer report diff_utc_mono=1685323259.020343
leak, time=1562403.055277, stack=0x7921948b54 0x7921948de4 0x7921c80e00 0x7923f99460 0x792433eee0, size=10485760, data=..................................................
leak, time=1562403.055280, stack=0x7921948b54 0x7921948de4 0x7921c83df4 0x7921c81dc8 0x7921c839e0, size=8, data=....y...

使用addr2line还原调试符号

很明显,我们看到stack都是符号地址,需要通过addr2line工具还原详细的信息

llvm-addr2line.exe -C -f -e libjni.so 0x7921948b54

建议使用ndk版本对应的addr2line,不过我发现其他版本的也可以,比如我使用的是:

ndk\23.1.7779620\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-addr2line.exe

so文件的路径:

app\build\intermediates\ndkBuild\debug\obj\local\arm64-v8a\*.so

至于使用哪个so,要看__builtin_frame_address函数所在的动态库模块

  • 如果libleaktracer是一个单独的so动态库,那么就应该使用libleaktracer.so(一般都是这种)
  • 如果libleaktracer被以静态库的方式引入到另外一个动态库,就应该使用target.so

addr2line显示??::

检查方向:

  • 确认so库的路径,以及是否携带调试符号信息

image.png

  • 确认使用的是项目编译sdk的addr2line
  • addr2line的地址参数,是否和so混用,so里面必须有该地址才能被正常识别。
  • 检查你的地址

检查你的地址

这个也是本篇文章我遇到的,0x7921948de4这种非常大的地址,一看就有问题。

每个进程都有自己独立的进程地址空间。该进程地址空间被划分为一系列连续的虚拟地址空间,每个虚拟地址对应着唯一的物理地址。

在 x86 架构的计算机中,操作系统会为每个进程分配一个虚拟地址空间,该空间从 0x00000000 到 0xFFFFFFFF(或者更少),共 4GB 的大小。

如果要使用 addr2line 工具查询动态链接库(DLL)中某个函数的源代码位置信息,通常需要将查询地址减去该 DLL 的基地址。

这是因为在 Windows 平台上,每个 DLL 都有一个基地址,用于确定该 DLL 中所有函数和变量在虚拟地址空间中的位置,以保证不同 DLL 之间的地址不会重叠冲突。

如果直接使用官方的源码,是没有处理基地址的问题,如果leak tracer以动态库的方式引入到项目,那么stakc地址是有问题的,导致你无论怎么试错,都无法得到正确的调试符号信息。

而处理这个基地址,一个非常重要的函数就是dladdr

leak traer所使用到的函数

__builtin_frame_address

void* __builtin_frame_address(unsigned int level);

GCC 内建函数之一,在 C/C++ 中使用时可以获取当前函数的堆栈帧指针(Frame Pointer)。

其中,level 参数表示向上返回堆栈帧的层级数。

如果 level 大于当前函数的堆栈帧层数,返回 NULL

有些linux系统返回的内存地址就是VMA地址

dladdr

获得指定地址所在的共享库信息,函数原型如下:

int dladdr(
    const void *addr, // 要查询的地址
    Dl_info *info     // 用于存储查询结果的结构体
);

Dl_info 结构体定义如下:

typedef struct {
    const char* dli_fname; /* 共享库文件名 */
    void* dli_fbase; /* 基地址 */
    const char* dli_sname; /* 符号名 */
    void* dli_saddr; /* 符号地址 */
} Dl_info;

dladdr 函数的返回值是非零表示查询成功,否则表示查询失败。如果查询成功,info 参数中会填充该地址所在的共享库文件名、基地址、符号名称和符号地址等信息。

示例结果:

dli_fbase: 0x791e321000, 
dli_fname:/data/app/~~M4EQtyRf9F8ogdMdo1pJEg==/com.example.jni-gHJ1rvzAUolWe7FDtjUucA==/base.apk!/lib/arm64-v8a/libjni.so, 
dli_saddr:0x791e33eb94, 
dli_sname:_Z12test_addressv

_Unwind_Backtrace

在 Android NDK 中,您可以使用 _Unwind_Backtrace 函数获取当前线程的函数调用栈信息。

目录
相关文章
|
6月前
|
运维 API 开发工具
当你下载并运行阿里云OpenAPI的工程时遇到“runtime error: invalid memory address or nil pointer
【1月更文挑战第8天】【1月更文挑战第38篇】当你下载并运行阿里云OpenAPI的工程时遇到“runtime error: invalid memory address or nil pointer
343 2
|
2月前
|
Linux
dynamic shadow call stack support
dynamic shadow call stack support
|
3月前
|
搜索推荐 Docker 容器
生信分析代码之前还好好的,怎么就报错了 Error in Ops. data. frame(guide_loc, panel_loc) :'==' only defined for equally-sized data frames
执行 `DimPlot` 函数时遇到错误 `;Error in Ops. data. frame(g guides_loc, panel_loc) : '==' only defined for equally-sized data frames`。解决方案和办法
997 0
生信分析代码之前还好好的,怎么就报错了 Error in Ops. data. frame(guide_loc, panel_loc) :'==' only defined for equally-sized data frames
|
5月前
|
监控 安全 Go
视觉智能开放平台操作报错合集之出现 panic: runtime error: invalid memory address or nil pointer dereference,该如何处理
在使用视觉智能开放平台时,可能会遇到各种错误和问题。虽然具体的错误代码和消息会因平台而异,但以下是一些常见错误类型及其可能的原因和解决策略的概述,包括但不限于:1. 认证错误、2. 请求参数错误、3. 资源超限、4. 图像质量问题、5. 服务不可用、6. 模型不支持的场景、7. 网络连接问题,这有助于快速定位和解决问题。
视觉智能开放平台操作报错合集之出现 panic: runtime error: invalid memory address or nil pointer dereference,该如何处理
|
编译器 Go 开发工具
JetBrains GoLand 以debug运行Go程序时出现could not launch process: decoding dwarf section info at offset 0x0: too short报错之保姆级别解决方案
JetBrains GoLand 以debug运行Go程序时出现could not launch process: decoding dwarf section info at offset 0x0: too short报错之保姆级别解决方案
275 0
|
Java
“Resource leak: ‘sc‘ is never closed”的解决及解释
“Resource leak: ‘sc‘ is never closed”的解决及解释
422 0
|
程序员 Go Windows
【go 语言】解决 grpc:--proto_path passed empty directory name. (Use "." for current directory.)
【go 语言】解决 grpc:--proto_path passed empty directory name. (Use "." for current directory.)
219 0
|
Java Maven 微服务
To see the full stack trace of the errors, re-run Maven with the -e switch.
问题描述 微服务项目中其它模块不能依赖common模块中的依赖 而common中是有依赖的
916 1
To see the full stack trace of the errors, re-run Maven with the -e switch.
|
数据库连接 Go
[Golang] runtime error: invalid memory address or nil pointer dereferenc报错
[Golang] runtime error: invalid memory address or nil pointer dereferenc报错
|
编解码 并行计算
wrf--运行real.exe时报错:“Could not find level above ground“ error
在修改wrf初始场资料时,如果做了带通滤波处理,会发现在运行real.exe时报错:“Could not find level above ground” error 。
wrf--运行real.exe时报错:“Could not find level above ground“ error