代码之家  ›  专栏  ›  技术社区  ›  M.M

字符串文本可以在posix_spawn的argv中传递吗?

  •  6
  • M.M  · 技术社区  · 7 年前

    为了 the posix_spawn function 其原型是:

    int posix_spawn(pid_t *restrict pid, const char *restrict path,
       const posix_spawn_file_actions_t *file_actions,
       const posix_spawnattr_t *restrict attrp,
       char *const argv[restrict], char *const envp[restrict]);
    

    值得注意的是, argv 参数指向的数组 char * 指针(即指向可变字符的指针)。此外,文档似乎并不能保证数据不会被写入。

    我的问题是:是否可以保证在某个地方传递字符串文本?或者我们是在冒着SegFault的风险?

    样本代码:

    char *v[] = { "foo.exe", "bar", NULL };
    posix_spawn( NULL, "foo.exe", NULL, NULL, v, NULL );
    
    3 回复  |  直到 7 年前
        1
  •  2
  •   R.. GitHub STOP HELPING ICE    7 年前

    在这里使用字符串文字是非常好的。

    指针参数(或由参数指向的指针数据)是否指向常量限定类型与函数是否可以修改指向对象无关。这纯粹是有关职能的契约问题。作为惯例,当不修改对象时,通常最好在参数中使用常量限定指针:

    1. 允许向常量限定对象传递指针而不进行强制转换,以及
    2. 表示对象不会被修改。

    但在c语言中没有这样做的要求。对于在接口中使用双指针类型的函数,这里通常有一个折衷方案。自从 T * const T * 不能互相别名,接口必须选择调用方更可能需要的窗体;如果调用方需要另一个窗体,则必须创建一个临时副本才能传递给函数。情况就是这样 posix_spawn .

    一般来说,当涉及到标准函数(c或posix)时,它们 不能有任何可观察到的副作用,除非指定 . 除非其将修改“属于”应用程序或应用程序有权访问的对象的功能文档说明,否则不能修改该对象;这样做不符合要求。这就是为什么返回指向静态存储的指针的函数显式地记录它的原因。例如,posix文档 strerror :

    返回的字符串指针可能无效,或者字符串内容可能被对strerror()的后续调用覆盖,

    如果没有此类文档,应用程序可以假定 斯特雷罗 不会被实现修改。

    自从 posix_繁殖 未记录以修改其指向的字符串 argv 数组,它不修改它们。

    此外,请注意 posix_繁殖 必须是线程安全的,并且不会对应用程序设置任何显式约束,以便并发访问 小精灵 串。因此,任何修改都会引入数据竞争,从而呈现 鱼卵 非螺纹安全,违反规范。

        2
  •  1
  •   Florian Weimer    7 年前

    char **argv 参数 main (和) execve )(尽管在具有适当流程分离的传统实现中,内核最终必须复制。)

    POSIX似乎并没有说这些数组是被修改的,但我很有信心现有的实现不会修改它们。使用不同参数(和可执行文件名)可能有一些原因,但是这些原因 如此 posix_spawn 无论如何,必须为副本分配内存,并且无法就地执行修改。

        3
  •  1
  •   chux    7 年前

    是否有保证可以传递字符串文本?或者我们是在冒着SegFault的风险?

    考虑到,存在技术故障风险 argv const 数组 char* 并提供 字符串文字 可能导致UB。用函数或者建模 main(int argc, char *argv[]) ,代码可以写入 argv[0] .

    int main(int argc, char *argv[])

    参数 argc 阿尔加夫 以及 阿尔加夫 阵列应为 可修改 在程序启动和程序终止之间保留它们最后存储的值。C11_§5.1.2.2.1 2

    int foo(......., char *const argv[restrict], char *const envp[restrict]);
    
    char *v[] = { "foo.exe", "bar", NULL };
    foo( NULL, "foo.exe", NULL, NULL, v, NULL );
    

    备选方案

    尽管有 posix_spawn() ,我怀疑是否会发生写入,使用c99的解决方案使用 复合文字 而不是 字符串文字 因此避免了ub电位。

    // char *v[] = { "foo.exe", "bar", NULL };
    char *v2[] = { (char [8]){"foo.exe"}, (char [4]){"bar"}, NULL };
    posix_spawn( NULL, "foo.exe", NULL, NULL, v2, NULL );
    

    现在 posix_spawn()生成 可以写入 v2[0]