У меня есть код на C ++, который использует NDK. Когда происходит сбой в коде C ++ (на устройстве; не через эмулятор), я получаю надгробную плиту (аварийный дамп), которая содержит стек вызовов глубиной всегда 2 уровня:
I/DEBUG ( 5089): pid: 5048, tid: 5062 >>> com.example.site <<<
I/DEBUG ( 5089): #00 pc 0059e08c /data/data/com.example.site/lib/libexample.so (_ZNK10MyNamespaceAPI11MyClass12GetDataEv)
I/DEBUG ( 5089): #01 lr 5bc9ef2c /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e764 5bce3070 /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e774 5bce309c /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e784 5bce2af4 /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e788 5c27ea9c /data/data/com.example.site/lib/libexample.so
Есть ли способ настроить мое приложение или Android, чтобы обеспечить более подробную информацию и глубину в стеке вызовов, распечатанном в аварийный дамп? Что на самом деле определяет это? Я видел несколько примеров, когда люди получают до 15 уровней глубины стека вызовов.
Механизм обратной трассировки, который развился за последние несколько лет, показывает столько кадров, сколько он может найти (до фиксированного предела 32, IIRC). Он остановится рано, если что-то помешает ему пройти дальше по стеку.
Механизм вызова в ARM помещает адрес возврата в регистр связи (LR), но компилятору разрешено передавать его в стек. Для функций «noreturn» его технически не нужно устанавливать вообще. Существуют псевдооперации на ассемблере, которые добавляют метаданные, которые помогают разобраться, где можно найти адрес возврата, и в более поздних версиях Android, которые должны все работать.
Когда вы получаете трассировку стека с двумя глубинами, это означает, что размотка не удалась в текущем методе, и она может показать вам только значение программного счетчика (ПК) и значение, которое оказывается в LR.
Убедитесь, что вы компилируете с -g
включить отладку.
Вызывающая функция вызывается напрямую из JNI? В некоторых старых версиях Android трассировка останавливается на мосту вызовов JNI из-за структуры кода, хотя это было исправлено в Dalvik назад в 2011. Последние устройства используют Art, хотя, как я ожидаю, по-другому.
Подобный вопрос Вот.