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

使用GCC编译C代码时传参引发段错误,C++编译无异常

FSCC卡测试工具C代码段错误问题排查

问题描述

我是有经验的C开发者,学习C语言时开发Fastcomm FSCC卡测试工具。最初用C引用传参、g++编译时无段错误且输出正常,改用gcc编译C代码后,编译无警告但运行出现段错误。经gdb调试确认,段错误由update_all_registers函数中访问结构体成员的操作导致。补充关键信息:FSCC_REGISTERS_INIT调用完全符合预期,会将整个结构体填充为'-1',段错误发生在访问结构体单个成员时。请问我的传参方式是否有误?

原代码

#include <fcntl.h>
#include <unistd.h>
#include <fscc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <ncurses.h>

int64_t get_current_time_ms()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

void update_all_registers(int fd, struct fscc_registers* regs)
{
    FSCC_REGISTERS_INIT(regs);
    regs->CMDR = FSCC_UPDATE_VALUE;
    regs->STAR = FSCC_UPDATE_VALUE;
    regs->CCR0 = FSCC_UPDATE_VALUE;
    regs->CCR1 = FSCC_UPDATE_VALUE;
    regs->CCR2 = FSCC_UPDATE_VALUE;
    regs->BGR = FSCC_UPDATE_VALUE;
    regs->SSR = FSCC_UPDATE_VALUE;
    regs->SMR = FSCC_UPDATE_VALUE;
    regs->TSR = FSCC_UPDATE_VALUE;
    regs->TMR = FSCC_UPDATE_VALUE;
    regs->RAR = FSCC_UPDATE_VALUE;
    regs->RAMR = FSCC_UPDATE_VALUE;
    regs->PPR = FSCC_UPDATE_VALUE;
    regs->TCR = FSCC_UPDATE_VALUE;
    regs->VSTR = FSCC_UPDATE_VALUE;
    ioctl(fd, FSCC_GET_REGISTERS, &regs);
}

void print_registers(struct fscc_registers* regs)
{
    printf("%.10llu 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x "
        "0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
        get_current_time_ms(), regs->CMDR, regs->STAR, regs->CCR0,
        regs->CCR1, regs->CCR2, regs->BGR, regs->SSR, regs->SMR, regs->TSR,
        regs->TMR, regs->RAR, regs->RAMR, regs->PPR, regs->TCR, regs->VSTR);
}

int main(void)
{
    int fd = 0;
    struct fscc_registers regs;
    fd = open("/dev/fscc0", O_RDWR);
    if (fd == -1)
    {
        perror("open");
        return EXIT_FAILURE;
    }
    FSCC_REGISTERS_INIT(regs);
    ioctl(fd, FSCC_GET_REGISTERS, &regs);
    printf("TS (ms)       CMDR       STAR       CCR0       CCR1       CCR2       BGR"
        "        SSR        SMR        TSR        TMR        RAR"
        "        RAMR       PPR        TCR        VSTR\n");
    print_registers(&regs);

    char odata[] = "This is a test";
    write(fd, odata, sizeof(odata));
    update_all_registers(fd, &regs);
    print_registers(&regs);

    close(fd);
    return 0;
}

问题根源与修正

你的传参逻辑存在两处关键错误,都集中在update_all_registers函数中:

1. FSCC_REGISTERS_INIT参数类型错误

FSCC_REGISTERS_INIT宏的设计目标是初始化结构体实例,而非结构体指针。你在main函数中调用FSCC_REGISTERS_INIT(regs)是正确的,但在update_all_registers中传入指针regs,会导致宏直接修改指针变量本身的内存(将其填充为'-1'),破坏了指针的有效地址。后续访问regs->CMDR时,指针已经指向非法内存,触发段错误。
修正:将宏调用改为对指针指向的结构体实例初始化:

FSCC_REGISTERS_INIT(*regs);

2. ioctl参数传递错误

FSCC_GET_REGISTERS命令要求传入struct fscc_registers*类型的指针,但你调用ioctl(fd, FSCC_GET_REGISTERS, &regs)时,regs本身已经是结构体指针,取地址后变成了二级指针struct fscc_registers**,内核无法正确解析这个地址,会导致后续操作异常。
修正:直接传入指针regs:

ioctl(fd, FSCC_GET_REGISTERS, regs);

修正后的update_all_registers函数

void update_all_registers(int fd, struct fscc_registers* regs)
{
    FSCC_REGISTERS_INIT(*regs);
    regs->CMDR = FSCC_UPDATE_VALUE;
    regs->STAR = FSCC_UPDATE_VALUE;
    regs->CCR0 = FSCC_UPDATE_VALUE;
    regs->CCR1 = FSCC_UPDATE_VALUE;
    regs->CCR2 = FSCC_UPDATE_VALUE;
    regs->BGR = FSCC_UPDATE_VALUE;
    regs->SSR = FSCC_UPDATE_VALUE;
    regs->SMR = FSCC_UPDATE_VALUE;
    regs->TSR = FSCC_UPDATE_VALUE;
    regs->TMR = FSCC_UPDATE_VALUE;
    regs->RAR = FSCC_UPDATE_VALUE;
    regs->RAMR = FSCC_UPDATE_VALUE;
    regs->PPR = FSCC_UPDATE_VALUE;
    regs->TCR = FSCC_UPDATE_VALUE;
    regs->VSTR = FSCC_UPDATE_VALUE;
    ioctl(fd, FSCC_GET_REGISTERS, regs);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:33:18