Skip to content

调试功能

Trae IDE 提供了强大的调试功能,支持多种编程语言和调试场景。本指南将介绍如何使用 Trae 的调试器来诊断和修复代码问题。

概述

Trae 调试器支持:

  • 多语言支持:JavaScript、TypeScript、Python、Java、C#、Go 等
  • 断点管理:行断点、条件断点、日志断点
  • 变量检查:局部变量、全局变量、监视表达式
  • 调用堆栈:完整的函数调用链
  • 步进调试:单步执行、步入、步出、继续
  • 远程调试:支持远程服务器和容器调试
  • 多线程调试:并发程序调试支持

快速开始

启动调试会话

  1. 打开文件:在编辑器中打开要调试的文件
  2. 设置断点:点击行号左侧设置断点
  3. 启动调试:按 F5 或点击调试按钮
  4. 选择配置:选择适当的调试配置

基本调试操作

操作快捷键描述
启动调试F5开始调试会话
停止调试Shift+F5终止调试会话
重启调试Ctrl+Shift+F5重新启动调试
继续执行F5继续到下一个断点
单步执行F10执行下一行代码
步入函数F11进入函数内部
步出函数Shift+F11退出当前函数
切换断点F9在当前行设置/移除断点

调试配置

launch.json 配置文件

调试配置存储在 .trae/launch.json 文件中:

json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Program",
            "type": "node",
            "request": "launch",
            "program": "${workspaceFolder}/app.js",
            "stopOnEntry": false,
            "args": [],
            "cwd": "${workspaceFolder}",
            "env": {
                "NODE_ENV": "development"
            },
            "console": "integratedTerminal",
            "sourceMaps": true
        }
    ]
}

常用配置属性

通用属性

  • name:配置显示名称
  • type:调试器类型(node、python、java 等)
  • request:请求类型(launch 或 attach)
  • program:要调试的程序入口
  • args:命令行参数
  • cwd:工作目录
  • env:环境变量
  • stopOnEntry:是否在入口处停止

Node.js 特定属性

json
{
    "type": "node",
    "request": "launch",
    "program": "${workspaceFolder}/server.js",
    "restart": true,
    "protocol": "inspector",
    "port": 9229,
    "address": "localhost",
    "sourceMaps": true,
    "outFiles": ["${workspaceFolder}/dist/**/*.js"],
    "skipFiles": [
        "<node_internals>/**",
        "node_modules/**"
    ],
    "envFile": "${workspaceFolder}/.env",
    "console": "integratedTerminal",
    "internalConsoleOptions": "neverOpen"
}

Python 特定属性

json
{
    "type": "python",
    "request": "launch",
    "program": "${workspaceFolder}/main.py",
    "python": "${command:python.interpreterPath}",
    "args": ["--verbose"],
    "django": false,
    "flask": {
        "app": "app.py",
        "env": {
            "FLASK_ENV": "development"
        }
    },
    "jinja": true,
    "justMyCode": true,
    "redirectOutput": true,
    "showReturnValue": true
}

Java 特定属性

json
{
    "type": "java",
    "request": "launch",
    "mainClass": "com.example.Main",
    "projectName": "my-project",
    "classPaths": [
        "${workspaceFolder}/target/classes"
    ],
    "modulePaths": [],
    "args": [],
    "vmArgs": "-Xmx1g",
    "encoding": "UTF-8",
    "console": "integratedTerminal"
}

断点管理

断点类型

行断点

最常用的断点类型,在指定行暂停执行:

  • 设置:点击行号左侧或按 F9
  • 移除:再次点击断点或按 F9
  • 禁用:右键点击断点选择"禁用断点"

条件断点

只在满足特定条件时触发的断点:

javascript
// 设置条件:i > 10
for (let i = 0; i < 20; i++) {
    console.log(i); // 断点只在 i > 10 时触发
}

设置方法:

  1. 右键点击行号
  2. 选择"添加条件断点"
  3. 输入条件表达式

日志断点

不暂停执行,只输出日志信息的断点:

javascript
// 日志消息:"Current value: {i}"
for (let i = 0; i < 10; i++) {
    processItem(i); // 日志断点输出当前 i 的值
}

设置方法:

  1. 右键点击行号
  2. 选择"添加日志点"
  3. 输入日志消息模板

函数断点

在函数被调用时触发的断点:

  1. 打开调试视图
  2. 在"断点"面板中点击"+"
  3. 选择"函数断点"
  4. 输入函数名

断点管理面板

调试视图中的断点面板提供:

  • 查看所有断点:显示项目中的所有断点
  • 批量操作:启用/禁用/删除多个断点
  • 断点分组:按文件分组显示
  • 断点搜索:快速查找特定断点

变量检查

变量面板

调试时,变量面板显示当前作用域中的变量:

局部变量

javascript
function calculateSum(a, b) {
    const result = a + b; // 局部变量:a, b, result
    const multiplier = 2;
    return result * multiplier;
}

全局变量

javascript
const globalConfig = { debug: true }; // 全局变量

function processData() {
    // 可以查看 globalConfig
}

监视表达式

添加自定义表达式来监视特定值:

  1. 在调试视图中找到"监视"面板
  2. 点击"+"添加表达式
  3. 输入要监视的表达式

常用监视表达式:

javascript
// 对象属性
user.name
user.settings.theme

// 数组长度
items.length

// 函数调用结果
getCurrentTime()

// 复杂表达式
items.filter(item => item.active).length

// 条件表达式
user.age >= 18 ? 'adult' : 'minor'

变量修改

在调试过程中可以修改变量值:

  1. 在变量面板中找到要修改的变量
  2. 双击变量值
  3. 输入新值
  4. 按 Enter 确认

调用堆栈

堆栈导航

调用堆栈显示函数调用链:

javascript
function main() {
    processUser(userData); // 堆栈帧 3
}

function processUser(user) {
    validateUser(user); // 堆栈帧 2
}

function validateUser(user) {
    checkEmail(user.email); // 堆栈帧 1 (当前)
}

function checkEmail(email) {
    // 断点位置 - 堆栈帧 0
}

堆栈操作

  • 切换帧:点击不同的堆栈帧查看对应的变量和代码
  • 复制堆栈:右键复制完整的调用堆栈
  • 过滤堆栈:隐藏库代码或内部函数

步进调试

步进类型

单步执行 (Step Over)

执行当前行,不进入函数内部:

javascript
const result = calculateSum(5, 3); // 执行整行,不进入 calculateSum
console.log(result); // 下一步到这里

步入 (Step Into)

进入函数内部进行调试:

javascript
const result = calculateSum(5, 3); // 步入会进入 calculateSum 函数

function calculateSum(a, b) {
    return a + b; // 步入后会停在这里
}

步出 (Step Out)

执行完当前函数并返回到调用处:

javascript
function calculateSum(a, b) {
    const sum = a + b; // 当前位置
    return sum; // 步出会执行完这个函数
}

const result = calculateSum(5, 3); // 步出后停在这里

智能步进

Trae 提供智能步进功能:

  • 跳过 getter/setter:自动跳过属性访问器
  • 跳过构造函数:跳过对象创建过程
  • 跳过库代码:不进入第三方库函数

配置智能步进:

json
{
    "debug.smartStep.skipFiles": [
        "<node_internals>/**",
        "node_modules/**",
        "${workspaceFolder}/lib/**"
    ],
    "debug.smartStep.skipGetters": true,
    "debug.smartStep.skipSetters": true
}

远程调试

Node.js 远程调试

启动远程调试服务器

bash
# 启动 Node.js 应用并开启调试端口
node --inspect=0.0.0.0:9229 app.js

# 或者在运行时附加调试器
node --inspect-brk=9229 app.js

配置远程调试

json
{
    "name": "Attach to Remote",
    "type": "node",
    "request": "attach",
    "address": "192.168.1.100",
    "port": 9229,
    "localRoot": "${workspaceFolder}",
    "remoteRoot": "/app",
    "sourceMaps": true
}

Docker 容器调试

Dockerfile 配置

dockerfile
FROM node:16

WORKDIR /app
COPY package*.json ./
RUN npm install

COPY . .

# 暴露调试端口
EXPOSE 3000 9229

# 启动时开启调试
CMD ["node", "--inspect=0.0.0.0:9229", "app.js"]

Docker Compose 配置

yaml
version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
      - "9229:9229"  # 调试端口
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development

调试配置

json
{
    "name": "Docker: Attach to Node",
    "type": "node",
    "request": "attach",
    "port": 9229,
    "address": "localhost",
    "localRoot": "${workspaceFolder}",
    "remoteRoot": "/app",
    "protocol": "inspector",
    "restart": true
}

SSH 远程调试

设置 SSH 隧道

bash
# 创建 SSH 隧道
ssh -L 9229:localhost:9229 user@remote-server

# 在远程服务器上启动调试
node --inspect=localhost:9229 app.js

调试配置

json
{
    "name": "SSH Remote Debug",
    "type": "node",
    "request": "attach",
    "address": "localhost",
    "port": 9229,
    "localRoot": "${workspaceFolder}",
    "remoteRoot": "/home/user/app"
}

多线程调试

线程管理

在多线程应用中,调试器显示所有活动线程:

python
import threading
import time

def worker_function(name):
    for i in range(5):
        print(f"Worker {name}: {i}")
        time.sleep(1)  # 断点可以设置在这里

# 创建多个线程
threads = []
for i in range(3):
    thread = threading.Thread(target=worker_function, args=(f"Thread-{i}",))
    threads.append(thread)
    thread.start()

# 等待所有线程完成
for thread in threads:
    thread.join()

线程切换

  • 线程面板:显示所有活动线程
  • 切换线程:点击不同线程查看其状态
  • 线程断点:为特定线程设置断点

并发调试技巧

  1. 使用条件断点:只在特定线程中触发
  2. 线程标识:在日志中包含线程 ID
  3. 同步点调试:在锁和信号量处设置断点
  4. 死锁检测:监视线程状态变化

调试控制台

交互式调试

调试控制台允许在调试过程中执行代码:

javascript
// 在调试控制台中执行
console.log(user.name); // 查看变量值
user.age = 25; // 修改变量
getUserPermissions(user.id); // 调用函数

// 复杂表达式
users.filter(u => u.active).map(u => u.name);

// 创建临时变量
const temp = processData(rawData);
console.log(temp);

控制台命令

特殊的调试控制台命令:

javascript
// 清除控制台
clear()

// 查看对象结构
dir(user)

// 性能测量
console.time('operation')
// ... 执行代码
console.timeEnd('operation')

// 堆栈跟踪
console.trace()

// 断言
console.assert(user.age > 0, 'Age must be positive')

性能调试

CPU 性能分析

Node.js 性能分析

json
{
    "name": "Launch with Profiling",
    "type": "node",
    "request": "launch",
    "program": "${workspaceFolder}/app.js",
    "profiling": {
        "enabled": true,
        "outputDir": "${workspaceFolder}/profiles"
    }
}

性能标记

javascript
// 添加性能标记
performance.mark('start-heavy-operation');

// 执行耗时操作
for (let i = 0; i < 1000000; i++) {
    // 复杂计算
}

performance.mark('end-heavy-operation');
performance.measure('heavy-operation', 'start-heavy-operation', 'end-heavy-operation');

// 查看性能数据
const measures = performance.getEntriesByType('measure');
console.log(measures);

内存调试

内存快照

javascript
// 触发垃圾回收
if (global.gc) {
    global.gc();
}

// 获取内存使用情况
const memUsage = process.memoryUsage();
console.log({
    rss: `${Math.round(memUsage.rss / 1024 / 1024)} MB`,
    heapTotal: `${Math.round(memUsage.heapTotal / 1024 / 1024)} MB`,
    heapUsed: `${Math.round(memUsage.heapUsed / 1024 / 1024)} MB`,
    external: `${Math.round(memUsage.external / 1024 / 1024)} MB`
});

内存泄漏检测

javascript
// 监控对象创建
const objects = new WeakSet();

class MyClass {
    constructor() {
        objects.add(this);
    }
}

// 定期检查内存使用
setInterval(() => {
    const memUsage = process.memoryUsage();
    if (memUsage.heapUsed > 100 * 1024 * 1024) { // 100MB
        console.warn('High memory usage detected');
    }
}, 5000);

调试最佳实践

断点策略

  1. 战略性设置断点

    • 在函数入口和出口设置断点
    • 在错误处理代码中设置断点
    • 在关键业务逻辑处设置断点
  2. 使用条件断点

    javascript
    // 只在特定条件下停止
    for (let i = 0; i < users.length; i++) {
        processUser(users[i]); // 条件:users[i].id === 'target-id'
    }
  3. 日志断点替代 console.log

    • 避免在代码中添加临时日志
    • 使用日志断点输出调试信息
    • 调试完成后自动清理

调试工作流

  1. 重现问题

    • 创建最小重现案例
    • 记录重现步骤
    • 准备测试数据
  2. 分析问题

    • 确定问题范围
    • 检查相关代码路径
    • 分析数据流
  3. 设置调试环境

    • 配置适当的调试配置
    • 设置必要的断点
    • 准备监视表达式
  4. 逐步调试

    • 从问题点向前追溯
    • 检查变量状态变化
    • 验证假设
  5. 验证修复

    • 测试修复后的代码
    • 运行相关测试用例
    • 确认问题解决

常见调试场景

异步代码调试

javascript
// Promise 调试
async function fetchUserData(userId) {
    try {
        const response = await fetch(`/api/users/${userId}`); // 断点 1
        const userData = await response.json(); // 断点 2
        return userData;
    } catch (error) {
        console.error('Failed to fetch user data:', error); // 断点 3
        throw error;
    }
}

// 回调函数调试
function processData(data, callback) {
    setTimeout(() => {
        const result = data.map(item => item * 2); // 断点
        callback(null, result);
    }, 1000);
}

事件驱动代码调试

javascript
// 事件监听器调试
document.addEventListener('click', function(event) {
    const target = event.target; // 断点
    if (target.classList.contains('button')) {
        handleButtonClick(target); // 断点
    }
});

// 自定义事件调试
class EventEmitter {
    emit(eventName, data) {
        const listeners = this.listeners[eventName] || [];
        listeners.forEach(listener => {
            listener(data); // 断点
        });
    }
}

错误处理调试

javascript
// 全局错误处理
process.on('uncaughtException', (error) => {
    console.error('Uncaught Exception:', error); // 断点
    // 记录错误信息
    process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
    console.error('Unhandled Rejection at:', promise, 'reason:', reason); // 断点
});

// Try-catch 调试
try {
    riskyOperation();
} catch (error) {
    if (error instanceof ValidationError) {
        handleValidationError(error); // 断点
    } else if (error instanceof NetworkError) {
        handleNetworkError(error); // 断点
    } else {
        handleUnknownError(error); // 断点
    }
}

故障排除

常见问题

断点不生效

可能原因和解决方案:

  1. 源映射问题

    json
    {
        "sourceMaps": true,
        "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  2. 文件路径不匹配

    json
    {
        "localRoot": "${workspaceFolder}",
        "remoteRoot": "/app"
    }
  3. 代码优化

    • 禁用代码压缩
    • 使用开发模式构建

调试器无法连接

检查清单:

  1. 端口是否开放

    bash
    netstat -an | grep 9229
    telnet localhost 9229
  2. 防火墙设置

    bash
    # 允许调试端口
    sudo ufw allow 9229
  3. 网络配置

    json
    {
        "address": "0.0.0.0", // 允许外部连接
        "port": 9229
    }

性能问题

优化建议:

  1. 减少断点数量

    • 移除不必要的断点
    • 使用条件断点
  2. 限制监视表达式

    • 避免复杂的监视表达式
    • 移除不需要的监视项
  3. 调整调试设置

    json
    {
        "debug.allowBreakpointsEverywhere": false,
        "debug.showInlineBreakpointCandidates": false
    }

调试器配置问题

环境变量问题

json
{
    "env": {
        "NODE_ENV": "development",
        "DEBUG": "app:*"
    },
    "envFile": "${workspaceFolder}/.env"
}

路径解析问题

json
{
    "cwd": "${workspaceFolder}",
    "program": "${workspaceFolder}/src/index.js",
    "outFiles": [
        "${workspaceFolder}/dist/**/*.js",
        "!**/node_modules/**"
    ]
}

高级调试技巧

调试器 API

javascript
// 程序化断点
if (someCondition) {
    debugger; // 触发调试器
}

// 条件调试
function complexFunction(data) {
    if (data.length > 1000) {
        debugger; // 只在大数据集时调试
    }
    // 处理逻辑
}

自定义调试命令

json
{
    "debug.console.acceptSuggestionOnEnter": "on",
    "debug.console.fontSize": 14,
    "debug.console.lineHeight": 1.2,
    "debug.console.wordWrap": true
}

调试扩展

安装有用的调试扩展:

  • Debugger for Chrome:浏览器调试
  • Python Debugger:Python 专用调试器
  • Java Debug:Java 应用调试
  • REST Client:API 调试

通过掌握这些调试技巧和工具,您可以更高效地诊断和修复代码问题。记住,良好的调试技能是成为优秀开发者的重要组成部分!

您的终极 AI 驱动 IDE 学习指南