内存问题检查工具

前言

本篇对查找常见内存问题的方法进行总结

常见的内存问题

Use after free:在指针释放后使用
Heap buffer overflow:堆溢出—堆对象读写越界
Stack buffer overflow:栈溢出—栈对象读写越界
Global buffer overflow:全局对象溢出—全局对象读写越界(bss&data)
Use after return:函数结束后仍使用栈中回收的变量
Use after scope:{}结束后仍使用其内变量
Initialization order bugs:全局变量初始化顺序
Memory leaks:内存泄露–使用后未释放、或者长期保持对象无法使虚拟机回收
内存数据未初始化

解决方案

Windows

VS工具链非常齐全,以上问题都有对应的工具集成
列如内存泄露,可以直接使用调试菜单的探查器,附加后截取快照即可。

跟着差异大的就行,是调用顺序。最后找到分配点,一般是使用了new或malloc的函数。

Mac

尚未了解
Mac OS 和iOS都是基于Darwin

IOS

尚未了解

Linux

检测工具同样十分齐全,常用Valgrind。
其建立在实现了虚拟机,时刻检测应用内存与CPU情况。

Android

工具目前最难用…
如果仅做java开发AS的功能完全够用了。
但是涉及到大量的native代码工具就很少了。

目前解决方案有几种:
将linux现有的工具移植到Android上,比如Valgrind。但是还是很不方便…
将Android应用使用的so库移植到arm linux上,使用linux上的工具探查。这个方案更加不靠谱,因为Android上的so库依赖了大量的Android系统so库,甚至使用了硬件支持。
google与民间开发的工具。

参考官方的几种方法:
https://developer.android.com/ndk/guides/debug
https://developer.android.com/studio/debug
https://source.android.com/devices/tech/debug/native-memory#libmemunreachable

https://cloud.tencent.com/developer/article/1192001
实际使用后,Address Sanitizer 是目前官方最支持的,但是一部分功能未实现,例如很需要的Leak
Malloc Debug有用,但是需要手动符号还原。简介:

AddressSanitizer
如果发现错误,应用会崩溃,且系统会将报告记录到日志中。
检测到错误时,ASan 会向标准输出和 logcat 发送一份详细报告,然后让进程崩溃。
LeakSanitizer是一个内存泄漏检测器,集成在AddressSanitizer中。该工具在x86_64 Linux和OS X上受支持。
LeakSanitizer默认在x86_64 Linux的ASan版本中启用,并且可以ASAN_OPTIONS=detect_leaks=1在x86_64 OS X上启用.LSan处于休眠状态直到进程结束,此时存在额外的泄漏检测阶段。在性能关键的场景中,LSan也可以在没有ASan仪器的情况下使用。
也就是说arm不支持

Malloc Debug
这是google bionic库带的检测方式。
注意点:py脚本运行win的程序不用带exe后缀。直接把那俩个从ndk取出来放同级目录就好
库文件本地构造成系统中的路径指明给脚本即可。
自己的库不要用pull的。去找带符号的。在\build\intermediates\cmake\debug\obj\arm64-v8。导出导入符号一定存在,但内部模块使用的符号一般不存在。需要debug模式编译且不要去符号。

杂补充

单一模块的符号是否导出由static等关键字或编译器属性决定。
针对链接器链接多个模块时,特别是生成动态、静态链接库时,导出的符号需要指定。
导出列表由编译器(或相关工具,如 CreateExportlist)在创建共享库的时候自动生成。也可以由开发人员手工编写。
详细使用可参考:https://www.ibm.com/developerworks/cn/aix/library/au-aix-symbol-visibility/index.html

记得程序员的自我修养中也有说过。

AS Native断点不起作用原因:

  1. Dubig Configuration 中的debug类型应该为双。 Auto没用
  2. setting中Build的instant Run。将瞬间启动热更新关闭,否则会app闪退

AS可以分别对java与native添加指令、内存断点、。
必须好好看完:
https://developer.android.com/studio/debug/?hl=zh-cn#watchpoints

程序静态分析综合平台:程序静态分析是指在不运行代码的方式下,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描分析,验证代码是否满足规范性、安全性、可靠性、可维护性,综合分析代码度量、覆盖率等指标的一种代码分析技术。

uses-permission:是权限
uses-feature:设备需要的软硬件

典型的跨平台代码

1
2
3
4
5
6
7
8
9
10
11
12
13
uint32_t get_thread_id()
{
#if defined(OS_WIN)
return (uint32_t)GetCurrentThreadId();
#elif defined(OS_ANDROID)
return (uint32_t)gettid();
#elif defined(OS_IOS) || defined(OS_OSX)
return (uint32_t)mach_thread_self();
#else
uv_thread_t id = uv_thread_self();
return *(uint32_t*)&id;
#endif
}

mount -o rw,remount -t 文件系统格式 挂载目录
我的n6p使用还要加auto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
android {
// 其他配置
sourceSets {
main {
jniLibs {//原生库目录
srcDir {
"src/main/jniLibs"
}
}
resources { //这个会按目录下的路径自动添加至lib、res、assets等 ---要复制到资源输出目录的非Java资源。
srcDir {
"src/main/shell"
}
}
}
}
}

参考

  1. https://blog.csdn.net/a740169405/article/details/81032228
  2. https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md