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

如何通过exec*系列函数向子进程传递整型变量?

解决exec*传递整型变量的问题

咱们直接拆解你遇到的问题:你想通过exec*系列函数给子进程传一个整型变量,但子进程拿到的值完全不对,对吧?先看看代码里的问题出在哪,再给你几个靠谱的解决办法。

为什么你的代码会出错?

首先得明确:exec*系列函数的所有参数都必须是以'\0'结尾的C风格字符串,这是它的设计要求。

你用union把int转成char数组tv.c,但这个数组里并没有自动添加'\0'结尾。比如你设置tv.i=12345,假设是小端字节序,对应的char数组是0x39 0x30 0x00 0x00——第三个字节就是'\0',所以execlp会把tv.c当成字符串"90"来传递,而不是完整的4字节数据。

到了子进程这边,你用memcpy(tv.c, av[0], sizeof(int)),但av[0]的实际长度只有2字节,硬读4字节就会越界,把内存里的随机数据读进来,结果自然就是那个奇怪的1627402297了。另外你还犯了一个小错误:execlp的第一个参数是程序路径,第二个参数应该是子进程的argv[0](通常是程序名),你直接传了tv.c,这也会导致argv的结构混乱。

几种正确的解决方法

方法1:把整型转成字符串传递(最推荐)

既然exec*就是用来传字符串的,那咱们就顺着它的设计来,把int转成字符串传过去,子进程再转回来。

父进程修改后代码:

/* parent */
#include <unistd.h>
#include <stdio.h>

int main(int ac, char *av[]) {
    int num = 12345;
    char num_str[20];
    // 把int转成字符串,确保有'\0'结尾
    snprintf(num_str, sizeof(num_str), "%d", num);
    if(fork() == 0) {
        // 注意:execlp的参数顺序是:程序路径 → argv[0] → 自定义参数 → 空指针
        execlp("./test", "./test", num_str, "abcd", (char *)0);
    }
    return 0;
}

子进程修改后代码:

/* child */
#include <stdio.h>
#include <stdlib.h>

int main(int ac, char *av[]) {
    // 把字符串转回int
    int num = atoi(av[1]);
    printf("child: ac=%d, num: %d, av1: %s\n", ac, num, av[2]);
    return 0;
}

运行后输出就是你想要的:child: ac=3, num: 12345, av1: abcd。

方法2:用管道传递二进制数据(适合复杂二进制结构)

如果一定要传递原始的二进制int(比如不想做字符串转换),可以用管道来实现——毕竟exec*的参数不适合传非字符串的二进制数据。

父进程代码:

/* parent */
#include <unistd.h>
#include <stdio.h>

int main(int ac, char *av[]) {
    int pipefd[2];
    // 创建管道,pipefd[0]是读端,pipefd[1]是写端
    pipe(pipefd);

    int num = 12345;
    if(fork() == 0) {
        close(pipefd[1]); // 子进程不需要写,关闭写端
        // 把管道读端重定向到标准输入,这样子进程可以从stdin读数据
        dup2(pipefd[0], STDIN_FILENO);
        execlp("./test", "./test", "abcd", (char *)0);
    } else {
        close(pipefd[0]); // 父进程不需要读,关闭读端
        // 把int写入管道
        write(pipefd[1], &num, sizeof(num));
        close(pipefd[1]);
    }
    return 0;
}

子进程代码:

/* child */
#include <unistd.h>
#include <stdio.h>

int main(int ac, char *av[]) {
    int num;
    // 从标准输入读入二进制int
    read(STDIN_FILENO, &num, sizeof(num));
    printf("child: ac=%d, num: %d, av0: %s\n", ac, num, av[1]);
    return 0;
}

这种方式直接传递二进制数据,没有字符串转换的开销,还能扩展传递结构体之类的复杂数据。

方法3:用环境变量传递(适合配置类参数)

你也可以把整型转成字符串后放到环境变量里,子进程读取环境变量再转回来,这样参数和业务数据可以分开。

父进程代码:

/* parent */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int ac, char *av[]) {
    int num = 12345;
    char env_var[20];
    snprintf(env_var, sizeof(env_var), "MY_NUM=%d", num);
    if(fork() == 0) {
        // 设置环境变量
        putenv(env_var);
        execlp("./test", "./test", "abcd", (char *)0);
    }
    return 0;
}

子进程代码:

/* child */
#include <stdlib.h>
#include <stdio.h>

int main(int ac, char *av[]) {
    // 读取环境变量
    char *num_str = getenv("MY_NUM");
    // 判空后转成int,默认值设为-1
    int num = num_str ? atoi(num_str) : -1;
    printf("child: ac=%d, num: %d, av0: %s\n", ac, num, av[1]);
    return 0;
}

最后再提醒一句

永远不要用exec*的参数传递非字符串的二进制数据,因为二进制数据里大概率会包含'\0',会导致参数被截断,或者子进程读取时越界,出现各种不可预测的bug。老老实实用字符串、管道或者环境变量,才是正确的姿势。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:36:20