fork / exec:stderr / stdout丢失了

时间:2015-05-05 15:55:50

标签: c fork stdout stderr

我写了一个程序,它启动一个新的进程组,然后分叉。

body {
	display: flex;
	flex-direction: column;
	height: 100vh;
}


footer {
	position: fixed;
    top: 180px;
	bottom: 0;
	width: 100%;
}

footer img[usemap] {
	height: auto;
	max-width: 100%;
	width: 100%;
}

如果我用

打电话
<svg height="250" width="500" style="position:relative;z-index:500;pointer-events:none;">
  <polygon points="220,10 300,210 170,250 123,234" fill="#CECECE" opacity="0.9" stroke="#000000" stroke-width="2" />
  Sorry, your browser does not support inline SVG.
</svg>    
</div>
<footer class="footer">
    <img src="http://www.wired.com/wp-content/uploads/2014/12/9-credit-1.jpg" alt="" usemap="#Map" name="#Map" id="map" style='z-index: -1'/>
    <map name="Map" id="Map">
    </map>
</footer>

它按预期工作。

如果我用

打电话
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char** argv) {
    if(0 != setpgid(0,0)) {
        fprintf(stderr, "Process group creation failed.");
    }
    pid_t pid = fork();
    if(-1 == pid) {
        // ups, error
        fprintf(stderr, "Fork failed!\n");
        return 1;
    } else if(0==pid) {
        // this is the child process
        char **partial = malloc((argc-1)*sizeof(char*));
        for(int i=1;i<argc;i++) {
            partial[i-1] = argv[i];
        }
        execvp(partial[0], partial);
        exit(127);
    }
    // this is the parent process
    int status;
    waitpid(pid, &status, 0);
    return status;
}

没有输出写入终端。那是为什么?

2 个答案:

答案 0 :(得分:0)

execve调用导致了段错误:

==22934== Command: ./testt bash -c echo\ Test
==22934== 
==22935== Syscall param execve(argv) points to unaddressable byte(s)
==22935==    at 0x4EF9537: execve (in /usr/lib64/libc-2.20.so)
==22935==    by 0x4EF9D35: execvpe (in /usr/lib64/libc-2.20.so)
==22935==    by 0x400822: main (testt.c:23)
==22935==  Address 0x51f2058 is 0 bytes after a block of size 24 alloc'd
==22935==    at 0x4C29BCF: malloc (in /usr/lib64/valgrind /vgpreload_memcheck-amd64-linux.so)
==22935==    by 0x4007C5: main (testt.c:18)
==22935== 

特别是,不要乱用argv [0](你不在这里,但只是说)。并且 - 这是关键 - 你必须strcpy()其他args到堆空间,而不仅仅是传递现有的指针。你没有分配那个argv,所以当启动例程再次运行时,不要指望它“坚持”等等......最后,你需要将NULL复制到参数列表的和。

答案 1 :(得分:-1)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

不要混合这样的标题。 sys / headers先行。

int main(int argc, char** argv) {
    if(0 != setpgid(0,0)) {
        fprintf(stderr, "Process group creation failed.");
    }
Yoda风格的比较看起来很糟糕,没有任何价值。

    pid_t pid = fork();
    if(-1 == pid) {
        // ups, error
        fprintf(stderr, "Fork failed!\n");
        return 1;
    } else if(0==pid) {
        // this is the child process
        char **partial = malloc((argc-1)*sizeof(char*));
        for(int i=1;i<argc;i++) {
            partial[i-1] = argv[i];
        }

这项练习有什么意义?如何使用argv ++,然后可以直接在execvp中使用它。你的循环是残暴和不必要的。你malloc argc - 1,但循环条件是i&lt; argc是不存在的,由另一种奇怪的东西弥补,我不是从0开始。错误诱导风格。

你也没有验证任何参数。

        execvp(partial[0], partial);

如果您检查错误,您会看到失败。最简单的“第一次接触”工具是strace,它会告诉你究竟是什么,见:

  

[pid 15735] execve(“/ usr / bin / bash”,[“bash”,“ - c”,“echo test”,   0x20fe1],[/ * 58 vars * /])= -1 EFAULT(错误地址)

从这一点可以看出,arg数组没有正确终止,并且内核试图复制垃圾。

所以,你的“回声测试”示例在纯粹意外时起作用,因为发生在那里有零。

如果你在malloc中启用了调试,那么它也会失败。

        exit(127);

这不是你如何退出没有执行的孩子。见_Exit。

    }
    // this is the parent process
    int status;
    waitpid(pid, &status, 0);
    return status;

此值不适合重新标注。请参阅waitpid联机帮助页中的相关宏。 shell支持从0到255的值。这将返回32512,可以被256整除,因此最终为0。

}