Return value of system() is not return value of executed program

半城伤御伤魂 提交于 2019-12-22 09:56:22

问题


I would like to execute an executable file whose main() returns 2 using system(). This is what I did

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

int main(int argc, char *agrv[])
{
    char command[7];
    strcpy(command, "./test1");
    printf("The return value: %d\n", system(command));

    return 0;
}

and test1 is

#include <stdio.h>

int main(void)
{
    printf("test1 has been executed and its return value is 2\n");

    return 2;
}

This is what I'm getting

test1 has been executed and its return value is 2
The return value: 512

My question is why I'm getting 512.


回答1:


The return value of system is actually the return value of waitpid() under POSIX.

status actually has a lot of information embedded in it:

From the system(3) manpage:

The following macros may be used to test the manner of exit of the process. One of the first three macros will evaluate to a non-zero (true) value:

WIFEXITED(status)

True if the process terminated normally by a call to _exit(2) or exit(3).

WIFSIGNALED(status)

True if the process terminated due to receipt of a signal.

WIFSTOPPED(status)

True if the process has not terminated, but has stopped and can be restarted.
This macro can be true only if the wait call specified the WUNTRACED option or if the child process is being traced (see ptrace(2)).

Depending on the values of those macros, the following macros produce the remaining status information about the child process:

WEXITSTATUS(status)

If WIFEXITED(status) is true, evaluates to the low-order 8 bits of the argument passed to _exit(2) or exit(3) by the child.

WTERMSIG(status)

If WIFSIGNALED(status) is true, evaluates to the number of the signal that caused the termination of the process.

WCOREDUMP(status)

If WIFSIGNALED(status) is true, evaluates as true if the termination of the process was accompanied by the creation of a core file containing an image of the process when the signal was received.

WSTOPSIG(status)

If WIFSTOPPED(status) is true, evaluates to the number of the signal that caused the process to stop.

Solution

#include <stdio.h>
#include <string.h>
#include <limits.h>

int main(int argc, char *argv[])
{
    int status;
    char command[PATH_MAX]; /* PATH_MAX is defined in sys/syslimits.h, included by limits.h */
    strcpy(command, "./test1");
    status = system(command);
    if ( WIFEXITED(status) ) {
          printf("The return value: %d\n", WEXITSTATUS(status));
    }
    else if (WIFSIGNALED(status)) {
          printf("The program exited because of signal (signal no:%d)\n", WTERMSIG(status));
    } 
    return 0;
}



回答2:


Quote man 3 system:

The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status).

man 2 wait shows the other information packed into the status returned by system(3).

  • 512 means the program exited with exit status 2.
  • 2 would mean the program was killed by signal 2 (SIGINT).

Note that that the string ./test1 takes 8 characters because of the trailing NUL. Your strcpy is clobbering some memory outside of command. Fix:

char command[8];
strcpy(command, "./test1");

Of course, there's no reason to make a copy in the first place.

const char* command = "./test1";
system(command)

or even

system("./test1")



回答3:


This is, in fact, undefined behavior. command only holds 7 characters, but your string "./test1" has 8, including the null-terminator. You'll need to either increase the size of command, or just call system directly with the literal string: system("./test1")



来源:https://stackoverflow.com/questions/24810889/return-value-of-system-is-not-return-value-of-executed-program

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!