JNI內(nèi)存調(diào)試指南

一建钥、相關(guān)背景

最近公司有個項目提出一個需求,就是在webrtc jni庫里面實現(xiàn)錄音虐沥,具體實現(xiàn)的細節(jié)為:

  • 采集揚聲器的聲音(對方聲音)
  • 采集麥克風的聲音(本地聲音)
  • 上述兩種聲音進行混音并回調(diào)到j(luò)ava層熊经。

我決定audio_tracnsport_imp.cc里面添加相關(guān)實現(xiàn)代碼泽艘,理由有以下幾點:

  • 在這個代碼里面,已經(jīng)實現(xiàn)了采集播放聲音的處理(背景噪聲消除镐依,消回聲匹涮,自動增益,頻率轉(zhuǎn)換等)槐壳,音質(zhì)最好然低。
  • 此處聲音接下來直接發(fā)送到對端,最接近對端播放感受务唐。

二雳攘、錄音大概實現(xiàn)

  • 1、在AudioTransportImpl::NeedMorePlayData函數(shù)采集揚聲器聲音:
int32_t AudioTransportImpl::NeedMorePlayData(const size_t nSamples,
                                             const size_t nBytesPerSample,
                                             const size_t nChannels,
                                             const uint32_t samplesPerSec,
                                             void* audioSamples,
                                             size_t& nSamplesOut,
                                             int64_t* elapsed_time_ms,
                                             int64_t* ntp_time_ms) {
  RTC_DCHECK_EQ(sizeof(int16_t) * nChannels, nBytesPerSample);
  RTC_DCHECK_GE(nChannels, 1);
  RTC_DCHECK_LE(nChannels, 2);
  RTC_DCHECK_GE(
      samplesPerSec,
      static_cast<uint32_t>(AudioProcessing::NativeRate::kSampleRate8kHz));

  // 100 = 1 second / data duration (10 ms).
  RTC_DCHECK_EQ(nSamples * 100, samplesPerSec);
  RTC_DCHECK_LE(nBytesPerSample * nSamples * nChannels,
                AudioFrame::kMaxDataSizeBytes);

  mixer_->Mix(nChannels, &mixed_frame_);
  *elapsed_time_ms = mixed_frame_.elapsed_time_ms_;
  *ntp_time_ms = mixed_frame_.ntp_time_ms_;

  const auto error = audio_processing_->ProcessReverseStream(&mixed_frame_);
  RTC_DCHECK_EQ(error, AudioProcessing::kNoError);

  nSamplesOut = Resample(mixed_frame_, samplesPerSec, &render_resampler_,
                         static_cast<int16_t*>(audioSamples));

  //此處采集處理揚聲器聲音
  voice_recorder_->onPlayoutVoice((int16_t *) mixed_frame_.data(),
                                      (int64_t) mixed_frame_.samples_per_channel_,
                                      (int64_t) mixed_frame_.sample_rate_hz_,
                                      (int64_t) mixed_frame_.num_channels_);

  RTC_DCHECK_EQ(nSamplesOut, nChannels * nSamples);
  return 0;
}
  • 2枫笛、在AudioTransportImpl::RecordedDataIsAvailabl函數(shù)采集麥克風聲音:
// Not used in Chromium. Process captured audio and distribute to all sending
// streams, and try to do this at the lowest possible sample rate.
int32_t AudioTransportImpl::RecordedDataIsAvailable(
    const void* audio_data,
    const size_t number_of_frames,
    const size_t bytes_per_sample,
    const size_t number_of_channels,
    const uint32_t sample_rate,
    const uint32_t audio_delay_milliseconds,
    const int32_t /*clock_drift*/,
    const uint32_t /*volume*/,
    const bool key_pressed,
    uint32_t& /*new_mic_volume*/) {  // NOLINT: to avoid changing APIs
  RTC_DCHECK(audio_data);
  RTC_DCHECK_GE(number_of_channels, 1);
  RTC_DCHECK_LE(number_of_channels, 2);
  RTC_DCHECK_EQ(2 * number_of_channels, bytes_per_sample);
  RTC_DCHECK_GE(sample_rate, AudioProcessing::NativeRate::kSampleRate8kHz);
  // 100 = 1 second / data duration (10 ms).
  RTC_DCHECK_EQ(number_of_frames * 100, sample_rate);
  RTC_DCHECK_LE(bytes_per_sample * number_of_frames * number_of_channels,
                AudioFrame::kMaxDataSizeBytes);

  int send_sample_rate_hz = 0;
  size_t send_num_channels = 0;
  bool swap_stereo_channels = false;
  {
    rtc::CritScope lock(&capture_lock_);
    send_sample_rate_hz = send_sample_rate_hz_;
    send_num_channels = send_num_channels_;
    swap_stereo_channels = swap_stereo_channels_;
  }

  std::unique_ptr<AudioFrame> audio_frame(new AudioFrame());
  InitializeCaptureFrame(sample_rate, send_sample_rate_hz, number_of_channels,
                         send_num_channels, audio_frame.get());
  voe::RemixAndResample(static_cast<const int16_t*>(audio_data),
                        number_of_frames, number_of_channels, sample_rate,
                        &capture_resampler_, audio_frame.get());

  ProcessCaptureFrame(audio_delay_milliseconds, key_pressed,
                      swap_stereo_channels, audio_processing_,
                      audio_frame.get());

  //采集麥克風聲音
  voice_recorder_->onRecordVoice(audio_frame.get());
  //忽略后續(xù)代碼
  ....
}

  • 后續(xù)進行聲音的重采樣吨灭、混音、然后回調(diào)到JAVA層刑巧,具體步驟不再贅述喧兄。

三、bug的一般調(diào)試手段

前面講了一堆無關(guān)主題的話啊楚,現(xiàn)在才進入正題吠冤。
由于在添加上述代碼后,我的程序出現(xiàn)了jni導(dǎo)致的閃退問題恭理。所以我開始查找問題根源; 由于jni代碼基本很難調(diào)試拯辙,只能在崩潰時獲取一點關(guān)鍵信息,例如以下:

----- timezone:GMT
05-07 12:24:16.332187  7971  8249 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x8 in tid 8249 (AudioTrackJavaT)
05-07 12:24:16.402427 14617 14617 I AEE/AED : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
05-07 12:24:16.404351 14617 14617 I AEE/AED : Build fingerprint: 'T28/T28:6.0/MRA58K/1568261156:user/test-keys'
05-07 12:24:16.404457 14617 14617 I AEE/AED : Revision: '0'
05-07 12:24:16.404542 14617 14617 I AEE/AED : ABI: 'arm'
05-07 12:24:16.404988 14617 14617 I AEE/AED : pid: 7971, tid: 8249, name: AudioTrackJavaT  >>> com.example.janusandroidtalk <<<
05-07 12:24:16.405157 14617 14617 I AEE/AED : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8
05-07 12:24:16.456888 14617 14617 I AEE/AED :     r0 f8e4a9e0  r1 00000008  r2 f8e4a9e0  r3 de492519
05-07 12:24:16.456985 14617 14617 I AEE/AED :     r4 f8e4a9e0  r5 de0adb04  r6 f8e46550  r7 de0a3eb2
05-07 12:24:16.457029 14617 14617 I AEE/AED :     r8 f8cddc48  r9 f8cddc40  sl f8cddca0  fp de09b88d
05-07 12:24:16.457071 14617 14617 I AEE/AED :     ip de5a8e74  sp dcc40398  lr de49252b  pc de1357c8  cpsr a00f0030
05-07 12:24:16.506852 14617 14617 I AEE/AED : 
05-07 12:24:16.506852 14617 14617 I AEE/AED : backtrace:
05-07 12:24:16.507029 14617 14617 I AEE/AED :     #00 pc 0018f7c8  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_Logging_nativeLog
05-07 12:24:16.507138 14617 14617 I AEE/AED :     #01 pc 004ec527  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507222 14617 14617 I AEE/AED :     #02 pc 00396061  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_YuvHelper_nativeI420Rotate  
05-07 12:24:16.507295 14617 14617 I AEE/AED :     #03 pc 00395ecf  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_YuvHelper_nativeI420Rotate
05-07 12:24:16.507364 14617 14617 I AEE/AED :     #04 pc 004ec687  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507436 14617 14617 I AEE/AED :     #05 pc 004ebe37  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507522 14617 14617 I AEE/AED :     #06 pc 004ebbe3  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507592 14617 14617 I AEE/AED :     #07 pc001e9f6f  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_Logging_nativeLog
05-07 12:24:16.507658 14617 14617 I AEE/AED :     #08 pc 001f2ecf  /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_audio_WebRtcAudioTrack_nativeGetPlayoutData
05-07 12:24:16.507752 14617 14617 I AEE/AED :     #09 pc 020dd5a3  /data/app/com.example.janusandroidtalk-1/oat/arm/base.odex (offset 0xf21000) (void org.webrtc.audio.WebRtcAudioTrack.nativeGetPlayoutData(long, int)+94)
05-07 12:24:16.507845 14617 14617 I AEE/AED :     #10 pc 020db771  /data/app/com.example.janusandroidtalk-1/oat/arm/base.odex (offset 0xf21000) (void org.webrtc.audio.WebRtcAudioTrack.access$300(long, int)+60)
05-07 12:24:16.507942 14617 14617 I AEE/AED :     #11 pc 020da8a1  /data/app/com.example.janusandroidtalk-1/oat/arm/base.odex (offset 0xf21000) (void org.webrtc.audio.WebRtcAudioTrack$AudioTrackThread.run()+1204)
05-07 12:24:16.508027 14617 14617 I AEE/AED :     #12 pc 000e60e1  /system/lib/libart.so (art_quick_invoke_stub_internal+64)
05-07 12:24:16.508108 14617 14617 I AEE/AED :     #13 pc 003e8b37  /system/lib/libart.so (art_quick_invoke_stub+170)
05-07 12:24:16.508187 14617 14617 I AEE/AED :     #14 pc 0010276c  [stack:8249]
05-07 12:24:17.637421 14617 14617 I AEE/AED : 
05-07 12:24:17.637421 14617 14617 I AEE/AED : Tombstone written to: /data/tombstones/tombstone_01

上述這種信息一般很難定位bug蚯斯,通常還需要用add2lin工具定位代碼:

cd ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/
./arm-linux-androideabi-addr2line -C -f -e libjingle_peerconnection_so.so 0018f7c8

以上操作一般只能定位到崩潰代碼函數(shù)名薄风,但是由于這個信息太少了饵较,一般找不到問題所在拍嵌,況且有時由于內(nèi)存越界會導(dǎo)致誤導(dǎo)性的崩潰堆棧提示。

四循诉、使用Sanitizers調(diào)試

Sanitizers是google開源的一款調(diào)試工具横辆,類似于valgrind,可以檢測包括內(nèi)存越界茄猫、訪問懸垂指針狈蚤、內(nèi)存泄露等bug,不過占用資源更少划纽,性能更強脆侮,在某些場景下比valgrind更適合。

Sanitizers在高版本的NDK里面已經(jīng)集成進去了(集成在clang編譯器內(nèi))勇劣,現(xiàn)在我們接下來講述怎么使用Sanitizers調(diào)試內(nèi)存錯誤靖避。

1潭枣、加入編譯參數(shù):

找打webrtc源碼根目錄下的編譯腳本(BUILD.gn),添加一下編譯flags:

#第98行修改
 ldflags = ["-fsanitize=address"]

#在第360行添加以下
cflags += [
      "-fsanitize=address",
      "-fno-omit-frame-pointer",
      "-g2",
      "-O0",
    ]

  cflags_c += [
      "-fsanitize=address",
      "-fno-omit-frame-pointer",
      "-g2",
      "-O0",
    ]

  cflags_cc += [
      "-fsanitize=address",
      "-fno-omit-frame-pointer",
      "-g2",
      "-O0",
    ]

上述修改主要是關(guān)閉編譯優(yōu)化、添加編譯調(diào)試符號幻捏、以及開啟Sanitizers內(nèi)存檢測盆犁。

2、重新編譯代碼

#構(gòu)建
gn gen out/Debug_arm --args='target_os="android" target_cpu="arm" is_debug=true'

#編譯
ninja -C out/Debug_arm

生成的webrtc動態(tài)庫在out/Debug_arm/libjingle_peerconnection_so.so.

3篡九、拷貝動態(tài)庫至app工程:

  • 拷貝libjingle_peerconnection_so庫:


    image.png
  • 拷貝libclang_rt.asan-arm-android.so庫:

cp ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/8.0.7/lib/linux/libclang_rt.asan-arm-android.so /path/to/armeabi-v7a

4谐岁、創(chuàng)建啟動腳本:

image.png

需要指出的是,腳本路徑是resources/lib/armeabi-v7a/wrap.sh榛臼,腳本內(nèi)容為:

#!/system/bin/sh
    HERE="$(cd "$(dirname "$0")" && pwd)"
    export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1,log_path=/sdcard/asan.log
    ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)
    if [ -f "$HERE/libc++_shared.so" ]; then
        # Workaround for https://github.com/android-ndk/ndk/issues/988.
        export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
    else
        export LD_PRELOAD="$ASAN_LIB"
    fi
    "$@"

上述腳本中指定了Sanitizerss生成日志路徑:/sdcard/asan.log

五伊佃、分析Sanitizers日志

找到Sanitizers日志并打開:

=================================================================
==32743==ERROR: AddressSanitizer: heap-use-after-free on address 0x81d8f934 at pc 0x71f047a3 bp 0x6c598990 sp 0x6c59898c
WRITE of size 4 at 0x81d8f934 thread T74 (AudioRecordJava)
    #0 0x71f047a0  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x242d7a0)
    #1 0x71f04176  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x242d176)
    #2 0x71efe490  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x2427490)
    #3 0x71eef78a  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x241878a)
    #4 0x71ee8adc  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x2411adc)
    #5 0x706d43c0  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xbfd3c0)
    #6 0x70769a72  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xc92a72)
    #7 0x70768c26  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xc91c26)
    #8 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #9 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #10 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #11 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #12 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #13 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #14 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #15 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #16 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #17 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #18 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #19 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #20 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #21 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #22 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #23 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #24 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #25 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #26 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #27 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #28 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #29 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #30 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #31 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #32 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #33 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #34 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #35 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #36 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #37 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #38 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #39 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #40 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #41 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #42 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #43 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #44 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #45 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #46 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #47 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #48 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #49 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #50 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #51 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #52 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #53 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #54 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #55 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #56 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #57 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #58 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #59 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #60 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #61 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #62 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #63 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #64 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #65 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #66 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #67 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #68 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #69 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #70 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #71 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #72 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #73 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #74 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #75 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #76 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #77 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #78 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #79 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #80 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #81 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #82 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #83 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #84 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #85 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #86 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #87 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #88 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #89 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #90 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #91 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #92 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #93 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #94 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #95 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #96 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #97 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #98 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #99 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #100 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #101 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #102 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #103 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #104 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #105 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #106 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #107 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #108 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #109 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #110 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #111 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #112 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #113 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #114 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #115 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #116 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #117 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #118 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #119 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #120 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #121 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #122 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #123 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #124 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #125 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #126 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #127 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #128 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #129 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #130 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #131 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #132 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #133 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #134 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #135 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #136 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #137 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #138 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #139 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #140 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #141 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #142 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #143 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #144 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #145 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #146 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #147 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #148 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #149 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #150 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #151 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #152 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #153 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #154 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #155 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #156 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #157 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #158 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #159 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #160 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #161 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #162 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #163 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #164 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #165 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #166 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #167 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #168 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #169 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #170 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #171 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #172 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #173 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #174 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #175 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #176 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #177 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #178 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #179 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #180 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #181 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #182 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #183 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #184 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #185 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #186 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #187 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #188 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #189 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #190 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #191 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #192 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #193 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #194 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #195 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #196 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #197 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #198 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #199 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #200 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #201 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #202 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #203 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #204 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #205 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #206 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #207 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #208 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #209 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #210 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #211 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #212 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #213 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #214 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #215 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #216 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #217 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #218 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #219 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #220 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #221 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #222 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #223 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #224 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #225 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #226 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #227 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #228 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #229 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #230 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #231 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #232 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #233 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #234 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #235 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #236 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #237 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #238 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #239 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #240 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #241 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #242 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #243 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #244 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #245 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #246 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #247 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #248 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #249 0xac98ca76  (/system/lib/libart.so+0x405a76)
    #250 0xac98ca76  (/system/lib/libart.so+0x405a76)

0x81d8f934 is located 4 bytes inside of 16-byte region [0x81d8f930,0x81d8f940)
freed by thread T56 (AudioTrackJavaT) here:
    #0 0xb3c8fb58  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xbeb58)
    #1 0x70159606  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x682606)
    #2 0xfff4c8a6  (<unknown module>)
    #3 0x28a6  (<unknown module>)

previously allocated by thread T74 (AudioRecordJava) here:
    #0 0xb3c8fee8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xbeee8)
    #1 0x70a5f54a  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xf8854a)
    #2 0x70cf5bf8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x121ebf8)
    #3 0xae65f0f8  (<unknown module>)

Thread T74 (AudioRecordJava) created by T45 (worker_thread -) here:
    #0 0xb3c78dc8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
    #1 0xac8fba2c  (/system/lib/libart.so+0x374a2c)

Thread T45 (worker_thread -) created by T43 (pool-9-thread-1) here:
    #0 0xb3c78dc8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
    #1 0x70baa018  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x10d3018)

Thread T43 (pool-9-thread-1) created by T31 (AsyncServer) here:
    #0 0xb3c78dc8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
    #1 0xac8fba2c  (/system/lib/libart.so+0x374a2c)

Thread T31 (AsyncServer) created by T0 (com.jimi.t28) here:
    #0 0xb3c78dc8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
    #1 0xac8fba2c  (/system/lib/libart.so+0x374a2c)

Thread T56 (AudioTrackJavaT) created by T45 (worker_thread -) here:
    #0 0xb3c78dc8  (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
    #1 0xac8fba2c  (/system/lib/libart.so+0x374a2c)

SUMMARY: AddressSanitizer: heap-use-after-free (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x242d7a0) 
Shadow bytes around the buggy address:
  0xa1041ed0: fa fa 00 04 fa fa 04 fa fa fa 00 00 fa fa 00 04
  0xa1041ee0: fa fa 00 04 fa fa 00 fa fa fa 00 fa fa fa fa fa
  0xa1041ef0: fa fa 00 04 fa fa 00 fa fa fa 04 fa fa fa fa fa
  0xa1041f00: fa fa 04 fa fa fa 00 00 fa fa 04 fa fa fa 04 fa
  0xa1041f10: fa fa fd fa fa fa 04 fa fa fa fd fd fa fa 04 fa
=>0xa1041f20: fa fa fd fd fa fa[fd]fd fa fa fd fd fa fa fd fd
  0xa1041f30: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fa fa
  0xa1041f40: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa
  0xa1041f50: fa fa 00 04 fa fa 00 00 fa fa 00 04 fa fa fd fd
  0xa1041f60: fa fa 04 fa fa fa fd fa fa fa fd fd fa fa fd fd
  0xa1041f70: fa fa fd fa fa fa 04 fa fa fa fd fd fa fa fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==32743==ABORTING

從上述日志可以看書,崩潰的原因是在AudioRecordJava線程非法寫入了一片已經(jīng)不存在的內(nèi)存沛善,這片內(nèi)存總共16個字節(jié)長锭魔,已經(jīng)被AudioTrackJavaT線程釋放,這片內(nèi)存最開始在AudioRecordJava線程創(chuàng)建路呜。

根據(jù)16進制的偏移量迷捧,使用addr2line可以定位到相關(guān)代碼。

六胀葱、總結(jié)

本次調(diào)試其實最終還是未找到bug漠秋,不過我相信這次總結(jié)后面應(yīng)該還能用到。

參考文章:
https://developer.android.com/ndk/guides/wrap-script
https://stackoverflow.com/questions/48870291/android-studio-address-sanitizer-using-build-gradle
https://developer.android.google.cn/ndk/guides/asan
https://www.linuxidc.com/Linux/2018-09/154273.htm
http://www.reibang.com/p/3a2df9b7c353

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抵屿,一起剝皮案震驚了整個濱河市庆锦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轧葛,老刑警劉巖搂抒,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尿扯,居然都是意外死亡求晶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門衷笋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芳杏,“玉大人,你說我怎么就攤上這事辟宗【粽裕” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵泊脐,是天一觀的道長空幻。 經(jīng)常有香客問我,道長容客,這世上最難降的妖魔是什么秕铛? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任则剃,我火速辦了婚禮,結(jié)果婚禮上如捅,老公的妹妹穿的比我還像新娘棍现。我一直安慰自己,他們只是感情好镜遣,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布己肮。 她就那樣靜靜地躺著,像睡著了一般悲关。 火紅的嫁衣襯著肌膚如雪谎僻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天寓辱,我揣著相機與錄音艘绍,去河邊找鬼。 笑死秫筏,一個胖子當著我的面吹牛诱鞠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播这敬,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼航夺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了崔涂?” 一聲冷哼從身側(cè)響起阳掐,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冷蚂,沒想到半個月后缭保,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蝙茶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年艺骂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尸闸。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡彻亲,死狀恐怖孕锄,靈堂內(nèi)的尸體忽然破棺而出吮廉,到底是詐尸還是另有隱情,我是刑警寧澤畸肆,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布宦芦,位于F島的核電站,受9級特大地震影響轴脐,放射性物質(zhì)發(fā)生泄漏调卑。R本人自食惡果不足惜抡砂,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恬涧。 院中可真熱鬧注益,春花似錦、人聲如沸溯捆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽提揍。三九已至啤月,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劳跃,已是汗流浹背谎仲。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留刨仑,地道東北人郑诺。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像杉武,于是被迫代替她去往敵國和親间景。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355