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

在C程序中调用strace出现Seg fault段错误的解决方法求助

问题描述

我不想直接从命令行调用strace,希望编写一个C程序来为指定程序运行strace。我尝试解决该问题数小时仍未成功,此前我曾编写过一个模拟Shell行为并将用户输入记录到日志文件的程序。我提取了其中相关代码,修改为运行strace ls,但程序无法正常工作,且出现了Seg fault (core dumped)错误。以下是我的代码:

#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 

int main () { 
    char *s = "strace ls"; 
    char* separator = " "; 
    char* argv[64]; 
    int argc = 0; 
    char* tmp; 

    printf("%s", s); 
    argv[argc] = strtok_r(s, separator, &tmp); 
    while( argv[argc] != NULL){ 
        argc+=1; 
        argv[argc] = strtok_r(NULL, separator, &tmp); 
    } 
    execvp(argv[0],argv); 
    return 0; 
}
问题分析与修复

你的程序触发段错误主要有两个核心问题:

  1. 修改只读字符串常量引发内存错误
    你定义的char *s = "strace ls";是一个字符串常量,它被存储在进程的只读数据段中。而strtok_r函数会直接修改传入的字符串(用\0替换分隔符),尝试修改只读内存自然会触发段错误。

    解决方法:把字符串常量改成栈上的可修改字符数组:

    char s[] = "strace ls";
    
  2. execvp要求参数列表以NULL结尾
    execvp的第二个参数是字符串数组,必须以NULL指针作为结尾标记,否则函数会超出数组范围访问内存,引发未定义行为(包括段错误)。

    解决方法:在填充完argv数组后,添加结束标记:

    argv[argc] = NULL;
    
修正后的完整代码
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 

int main () { 
    // 改为栈上可修改的字符数组
    char s[] = "strace ls"; 
    char* separator = " "; 
    char* argv[64]; 
    int argc = 0; 
    char* tmp; 

    printf("%s\n", s); 
    argv[argc] = strtok_r(s, separator, &tmp); 
    while( argv[argc] != NULL){ 
        argc += 1; 
        argv[argc] = strtok_r(NULL, separator, &tmp); 
    }
    // 为execvp添加参数列表结束标记
    argv[argc] = NULL;
    execvp(argv[0], argv); 
    // 如果execvp执行到这里,说明调用失败,打印错误信息
    perror("execvp failed");
    return 1; 
}

额外加了perror调用,这样如果execvp执行失败(比如找不到strace命令),你能看到具体的错误原因,方便后续调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:57:39