简体   繁体   中英

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

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 .

Quote man 3 system :

The value returned is -1 on error (eg 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")

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;
}

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")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM