You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下VSCode调试C程序时fopen函数异常问题排查

问题:Ubuntu下VSCode调试C程序时fopen单步进入异常退出

我在Ubuntu系统下使用VSCode编写C程序,代码实际功能为将文件最后一行打印到stdout(顶部注释描述的功能与实际不符,本次问题与功能无关):

/*
    Usage: ./reverse [input] [output]

    Algorithm:
    Builds a linked list of strings, each for a line in [input],
    and then walk the nodes backward to build the [output]
*/

#include "stdio.h"
#include "stdlib.h"
#include <stdint.h>
#include <stdbool.h>

int main(int argc, char* argv[]) {
    if (argc != 2) {
        printf("Usage: ./reverse [filename]\n");
        exit(EXIT_FAILURE);
    }
    // breakpoint set at next line
    char* filename = argv[1];
    FILE* fp = fopen(filename, "r");
    if (fp == NULL) {
        printf("Cannot open file %s\n", filename);
        exit(EXIT_FAILURE);
    }
    // StackOverflow users please ignore the rest of the code
    // fseek() to the end of file and move back to find EOL
    int64_t offset = 1;
    int64_t offsetNextEOL = 0;
    int64_t offsetThisEOL = 0;
    while (true) {
        if (fseek(fp, -offset, SEEK_END) != 0) {
            fprintf(stderr, "fseek() error\n");
        }
        else {
            char ch = fgetc(fp);
            if (ch == '\n') {
                // print the last line to stdout
                offsetThisEOL = ftell(fp);
                if (offsetNextEOL < offsetThisEOL) {
                    // We just found the last EOL so print everything from it to EOF
                    if (fseek(fp, 0, SEEK_END) != 0) {
                        fprintf(stderr, "fseek() error\n");
                    }
                    int64_t offsetEOF = ftell(fp);
                    int64_t offsetDiff = offsetEOF - offsetThisEOL;
                    // Now seek back to offsetThisEOL and start print
                    if (fseek(fp, -offsetThisEOL, SEEK_END) != 0) {
                        fprintf(stderr, "fseek() error\n");
                    }
                    for (int64_t i = 0; i < offsetDiff; i++) {
                        printf("%c", fgetc(fp));
                    }
                    // For the last line, no need to print EOL

                    // We just found the last EOL so need to set up offsetNextEOL
                    offsetNextEOL = offsetThisEOL;
                }
                break;
            }
        }
        offset++;
    }

    exit(EXIT_SUCCESS);
}

目录结构如下(所有文件在同一文件夹):

-os
  -.vscode
  -utils
    reverse.c
    reverse
    reverse.txt

我的launch.json配置如下:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
    {
        "name": "(gdb) Launch",
        "type": "cppdbg",
        "request": "launch",
        "program": "${workspaceRoot}/utils/reverse",
        "cwd": "${workspaceRoot}/utils",
        "args": ["reverse.txt"],
        "MIMode": "gdb",
        "setupCommands": [
            {
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            },
            {
                "description": "Set Disassembly Flavor to Intel",
                "text": "-gdb-set disassembly-flavor intel",
                "ignoreFailures": true
            }
        ]
    }
    ]
}

我在char* filename = argv[1];行设置了断点,调试时发现执行到fopen()函数,单步进入后调试器仅闪三下,无任何特殊提示便以代码0退出。我猜测是路径问题但无法定位,请问问题出在哪里?


解决方案

1. 确保编译时添加调试信息

编译程序时必须加上-g参数,否则gdb无法正确解析标准库函数的调试信息,单步进入时会出现异常退出。正确的编译命令为:

gcc -g reverse.c -o reverse

2. 安装libc调试符号

Ubuntu默认未安装标准库的调试符号,导致gdb无法进入fopen等系统函数。执行以下命令安装:

sudo apt-get install libc6-dbg

安装完成后重新调试,即可正常单步进入标准库函数。

3. 验证文件路径与权限

虽然配置中设置了cwd为${workspaceRoot}/utils,但可以在断点后添加打印语句验证filename的值:

printf("当前要打开的文件:%s\n", filename);

重新编译调试,确认输出的文件名是否正确,同时检查reverse.txt是否存在、是否有读权限:

ls -l ./reverse.txt

4. 调整调试配置的启动断点

在launch.json的配置项中添加"stopAtEntry": true,让程序启动时直接停在main函数入口,再逐步调试,便于排查问题:

{
    "name": "(gdb) Launch",
    "type": "cppdbg",
    "request": "launch",
    "program": "${workspaceRoot}/utils/reverse",
    "cwd": "${workspaceRoot}/utils",
    "args": ["reverse.txt"],
    "stopAtEntry": true, // 新增该配置
    "MIMode": "gdb",
    "setupCommands": [
        {
            "description": "Enable pretty-printing for gdb",
            "text": "-enable-pretty-printing",
            "ignoreFailures": true
        },
        {
            "description": "Set Disassembly Flavor to Intel",
            "text": "-gdb-set disassembly-flavor intel",
            "ignoreFailures": true
        }
    ]
}

内容的提问来源于stack exchange,提问作者Nicholas Humphrey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:14:59