【问题标题】:Return value of system() is not return value of executed programsystem() 的返回值不是执行程序的返回值
【发布时间】:2014-09-08 18:12:22
【问题描述】:

我想使用system() 执行一个main() 返回2 的可执行文件。 这就是我所做的

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

test1

#include <stdio.h>

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

    return 2;
}

这就是我得到的

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

我的问题是为什么我会收到512

【问题讨论】:

  • @AntonH OP 并不打算打印字符串。
  • @AntonH 不,你错了
  • @DrewMcGowen 你说得对,我读得太快了。
  • command 太小。这是未定义的行为。
  • Here 是用户获得 512 的链接。在这种情况下,它与 SQL 调用结合使用。

标签: c return main


【解决方案1】:

system的返回值其实就是POSIX下waitpid()的返回值。

status其实嵌入了很多信息:

来自 system(3) 手册页:

以下宏可用于测试退出方式 过程。前三个宏之一将评估为非零 (真)值:

WIFEXITED(status)

True 如果进程通过调用 _exit(2) 或 exit(3) 正常终止。

WIFSIGNALED(status)

True 如果进程因收到信号而终止。

WIFSTOPPED(status)

True 如果进程没有终止,但已经停止并且可以重新启动。
仅当等待调用指定 WUNTRACED 选项或是否正在跟踪子进程(请参阅 ptrace(2))。

根据这些宏的值,以下宏会产生 子进程的剩余状态信息:

WEXITSTATUS(status)

如果WIFEXITED(status)true,则计算为子级传递给_exit(2) 或exit(3) 的参数的低8 位。

WTERMSIG(status)

如果 WIFSIGNALED(status)true,则计算为导致 终止进程。

WCOREDUMP(status)

如果WIFSIGNALED(status)true,则如果进程的终止伴随着创建包含接收信号时进程图像的核心文件,则评估为真。

WSTOPSIG(status)

如果WIFSTOPPED(status)true,则计算为导致进程停止的信号编号。

解决方案

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

【讨论】:

  • WIFEXITED ... etc 函数在哪里?我遇到了错误。
  • WIFEXITED 应使用system(3)wait(2) 函数记录。否则请参阅 POSIX.1 (2013) sys/wait.h
【解决方案2】:

引用man 3 system

错误时返回值为-1(例如fork(2) 失败),否则返回命令状态。后一种返回状态采用wait(2) 中指定的格式。因此,该命令的退出代码将是WEXITSTATUS(status)

man 2 wait 显示由system(3) 返回的status 中包含的其他信息。

  • 512 表示程序以退出状态 2 退出。
  • 2 表示程序被信号 2 (SIGINT) 杀死。

请注意,字符串 ./test1 需要 8 个字符,因为尾随 NUL。你的strcpy 正在破坏command 之外的一些内存。修复:

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

当然,一开始就没有理由复制。

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

甚至

system("./test1")

【讨论】:

  • 现在我应该如何获得2?我需要使用这个值。每个人都在解决问题,但不是解决方案。
  • @CroCo 如果您不理解问题,那么您将不会理解答案。目标是让您学习自己修复错误,而不是免费调试。
  • @mctylr,如果您已尽力解决问题但失败了,那么让其他人调试代码是没有问题的。请停止炫耀,好像你是唯一一个努力工作的人。
  • @CroCo,我告诉过你解决方案。 "该命令的退出代码将是WEXITSTATUS(status)。"
  • @CroCo,ikegami 已经回答了您关于为什么以及如何解释来自system返回值 的问题,这样您就可以确定 退出代码执行了命令system。此外,他们还指出,您还有第二个问题干扰了您想要的结果。如果你不明白这个答案,那么澄清你不明白哪一部分?
【解决方案3】:

事实上,这是未定义的行为。 command 仅包含 7 个字符,但您的字符串 "./test1" 包含 8 个字符,包括空终止符。您需要增加command 的大小,或者直接使用文字字符串调用systemsystem("./test1")

【讨论】:

  • +1 这并不能完全回答 OP 的问题,但肯定解决了一个严重的错误。
  • 好吧,从技术上讲,由于 OP 正在调用 UB,因此 512 的返回值可能是 UB 的结果。
  • 作为评论会更好。
  • 这不是 OP 问题的答案
  • 其实 OP 的问题实际上是 why“我的问题是为什么我 [sic] 得到 512[?]”跨度>
猜你喜欢
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 2011-07-13
  • 2018-03-06
相关资源
最近更新 更多