Debug (modo de depuração) — é uma configuração de compilação para aplicações móveis na qual o compilador inclui informação simbólica, desativa a otimização de código e conecta o depurador para análise passo a passo da execução. De acordo com Android Developers, uma compilação Debug contém símbolos de depuração, não comprime recursos e permite conectar um inspetor de banco de dados e requisições de rede. O modo Debug se contrapõe à compilação Release: no Debug, o desenvolvedor sacrifica desempenho pela transparência da execução do código.
Pontos principais
Debug não é apenas uma flag do compilador, mas um conjunto completo de configurações que tornam a aplicação transparente para o desenvolvedor. No modo Debug, o compilador adiciona uma tabela de nomes simbólicos (DWARF) ao arquivo executável, que liga o código de máquina às linhas de código fonte. Sem esta tabela, o depurador não consegue mostrar qual linha de código está sendo executada no momento.
Depurador (debugger) é um programa que executa sua aplicação em um ambiente controlado. Você pode pausar a execução em qualquer linha (breakpoint), visualizar os valores de todas as variáveis no escopo atual, alterá-los em tempo real e continuar a execução. Para plataformas móveis, o depurador padrão é o LLDB — um componente do LLVM usado tanto no Xcode quanto no Android Studio.
O modo Debug também inclui verificações adicionais que estão desativadas no Release: asserções, verificações de limites de arrays, detectores de vazamento de memória e registro ampliado. Essas verificações diminuem a aplicação mas detectam erros nos estágios iniciais do desenvolvimento — antes que o código chegue ao usuário.
A diferença entre compilações Debug e Release é fundamental: são dois conjuntos diferentes de flags do compilador, configurações de assinatura e ajustes de empacotamento. Compreender essas diferenças ajuda a evitar situações em que “funciona no simulador mas não no dispositivo real”.
| Parâmetro | Debug | Release |
|---|---|---|
| Otimização | Desativada (-O0) | Ativada (-Os ou -O2) |
| Símbolos | Tabela DWARF completa | Removidos |
| Assinatura | Certificado de desenvolvimento | Certificado de distribuição |
| Perfis | Perfil de provisionamento Debug | Perfil App Store / Ad Hoc |
| Registro | Completo (todos os níveis) | Desativado ou mínimo |
| Ofuscação | Desativada | Ativada (ProGuard/R8) |
| Tamanho .apk/.ipa | Maior (símbolos + sem compressão) | Menor (R8 + recursos) |
Compilação Debug é usada em todas as etapas de desenvolvimento e teste em dispositivos locais. A compilação Release é gerada antes de enviar para App Store Connect ou Google Play Console. Depurar em uma compilação Release é tecnicamente possível mas extremamente inconveniente devido aos métodos renomeados (R8) e à falta de symbolication para logs de falhas.
Um problema comum é código que funciona em Debug mas falha em Release. A causa é UB (comportamento indefinido) no código que o compilador trata de forma diferente com diferentes níveis de otimização. Um exemplo típico: ler uma variável não inicializada ou violar strict aliasing. Para detectar esses erros, use um analisador estático (Clang Static Analyzer, ktlint) antes de cada compilação Release.
LLDB é um depurador de alto desempenho baseado em LLVM, compatível com C, C++, Objective-C, Swift e Kotlin/Native. LLDB fornece uma interface REPL onde você pode executar expressões arbitrárias, alterar valores de variáveis e chamar funções no contexto de uma aplicação pausada.
Breakpoint é uma ferramenta chave do depurador. Você coloca um ponto em uma linha de código e a aplicação pausa quando a execução chega nessa linha. LLDB suporta vários tipos de breakpoints: condicionais (disparam apenas quando uma condição é atendida), simbólicos (em chamadas de função) e de uso único (disparam uma vez e são removidos automaticamente).
Watchpoint é um ponto de observação de alterações em uma variável. Você especifica um endereço de memória e o depurador pausa a execução em qualquer escrita nesse endereço. Esta ferramenta é indispensável para encontrar condições de corrida e mutações incorretas de objetos compartilhados. Para ver a hierarquia do UIKit, use o UIView Inspector disponível no Xcode.
// Definir breakpoint condicional
(lldb) breakpoint set --name "viewDidLoad" --condition "self.isViewLoaded == false"
// Watchpoint em propriedade
(lldb) watchpoint set variable self->_loadingState
// Executar código no contexto parado
(lldb) expr self.view.backgroundColor = UIColor.redColor
Ambas as IDEs fornecem inspetores gráficos sobre o LLDB. Android Studio inclui Layout Inspector (hierarquia de Views), Network Inspector (rastreamento de requisições HTTP) e Database Inspector (SQLite em tempo real). Xcode fornece Debug Memory Graph (análise de vazamento de memória) e View Debugger (visualização 3D das camadas UIKit).
A partir do Android 11, a depuração por Wi-Fi funciona sem conexão USB: basta escanear o código QR do Android Studio. O iOS suporta depuração por Wi-Fi desde o Xcode 9+ — o dispositivo conecta uma vez via USB, após o que as sessões de depuração podem ocorrer pela rede. A depuração por Wi-Fi não é adequada para servidores CI devido à latência imprevisível e perda de pacotes, portanto pipelines automatizados sempre usam USB. No entanto, para desenvolvimento local, a depuração por Wi-Fi é notavelmente mais conveniente — o desenvolvedor não fica preso a um cabo e pode testar a aplicação em um dispositivo do outro lado da sala.
Android Debug Bridge (ADB) é uma ferramenta universal para interagir com um dispositivo Android pela linha de comando. Através do ADB você pode instalar uma aplicação, iniciar a depuração, copiar arquivos, executar comandos shell e visualizar logs. O Android Studio usa o ADB internamente para todas as operações de depuração.
Android Studio suporta dois modos de depuração: Run (inicialização normal) e Debug (inicialização com o depurador conectado). No modo Debug você pode definir breakpoints diretamente no editor, inspecionar variáveis na janela Debug Tool e avaliar expressões no Evaluate Expression. Para depurar processos em segundo plano (Service, BroadcastReceiver), use Attach Debugger to Android Process.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Breakpoint aqui pausará a execução
val button = findViewById<Button>(R.id.btn_debug)
button.setOnClickListener {
startDebugProcess()
}
}
private fun startDebugProcess() {
val data = fetchDataFromApi()
Log.d("Debug", "Data loaded: $data")
}
}
Comandos shell ADB fornecem acesso ao sistema de arquivos do dispositivo sem privilégios root. Você pode visualizar o conteúdo do diretório databases, copiar o arquivo .db para seu computador e abri-lo com qualquer cliente SQLite. O Android Studio Database Inspector automatiza esse processo: você vê dados do banco de dados ao vivo em tempo real e pode executar consultas SQL diretamente da IDE.
Xcode fornece um ambiente de depuração integrado baseado em LLDB. O desenvolvedor pode executar a aplicação em um simulador ou dispositivo físico, definir breakpoints e usar o Debug Navigator para controlar as threads de execução. Diferente do Android, o iOS não permite executar duas compilações Debug simultaneamente no mesmo dispositivo sem configuração especial.
O simulador executa a aplicação como um processo nativo do macOS, proporcionando o ciclo de depuração mais rápido. Em um dispositivo físico, a depuração ocorre via USB ou Wi-Fi (a partir do iOS 16), e o LLDB se comunica com o debugserver no dispositivo. O desempenho da depuração no dispositivo é menor devido à largura de banda limitada do USB 2.0, mas apenas um dispositivo físico permite testar cenários reais: notificações push, câmera, sensores.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
private func setupUI() {
let label = UILabel()
label.text = "Modo Debug"
label.textColor = .systemBlue
view.addSubview(label)
}
}
Xcode Organizer coleta logs de falha dos dispositivos dos testadores através de Crash Logs. Para symbolication (converter endereços em nomes de funções) é necessário o arquivo .dSYM, que é gerado com cada compilação Debug. Em uma compilação Release, o dSYM também é criado, mas os logs de falha da App Store precisam ser enviados ao Organizer manualmente ou através do serviço bitcode.
Perguntas frequentes
Tecnicamente sim — através de distribuição Ad Hoc com um certificado Debug, mas Apple e Google não recomendam isso. Uma compilação Debug contém símbolos de depuração e desempenho reduzido, o que degrada a UX e aumenta o tamanho da aplicação em 2–3 vezes.
A razão é a otimização do compilador desativada (-O0). O compilador não inline funções, não remove código morto e mantém todas as variáveis intermediárias. Além disso, Debug inclui verificações de asserções e limites de arrays que estão ausentes no Release.
No Xcode escolha Window → Devices and Simulators, marque “Connect via network” para seu dispositivo. O dispositivo e o Mac devem estar na mesma rede Wi-Fi. Após conectar via USB uma vez, a depuração funcionará por Wi-Fi nas execuções subsequentes.
Attach to process permite conectar o depurador a um processo já em execução sem reiniciar a aplicação. Isso é útil para depurar Services, BroadcastReceivers ou processos que iniciam por um evento do sistema, onde o Debug Run padrão não é aplicável.
NSLog e print por padrão exibem logs apenas na configuração Debug. Para Release, use os_log com a flag OSLogType.default — ele salva mensagens no Unified Logging System e é acessível através do Console.app no Mac.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também