C中的system()时出现分段错误

时间:2018-12-18 15:45:21

标签: c terminal segmentation-fault

我想使用linux的“ base64”脚本对数据进行编码并以C语言获取。 当我尝试编译

char a[200];
strcpy(a, "Hello");
printf("%s", a);

我得到了输出

Hello

现在,只要我尝试输入代码

char a[200];
strcpy(a, system("echo Hello | base64"));
printf("%s", a);

我得到了输出

aGVsbG8K
Segmentation fault

即使删除了“ printf”语句,我也会得到相同的结果

aGVsbG8K
Segmentation fault

我要保存

的输出值
system("echo Hello | base64")

在“ a”中不显示。请帮助

2 个答案:

答案 0 :(得分:6)

如果您阅读system的文档,则会发现它没有返回字符串-定义为:

int system(const char *command);

返回值是命令的返回状态;如果有错误,则返回-1。您无法使用system获得输出-您运行的命令的输出将直接转到stdout。

要从另一个命令获取输出,可以使用类似popen的东西。

FILE *myfile;
char buffer[1024];

myfile=popen("echo Hello | base64","r");
if(myfile)
  {
  while(fgets(buffer,1024,myfile))
    {
    printf("%s",buffer);
    }

  pclose(myfile);
  }

答案 1 :(得分:0)

这里

strcpy(a, system("echo Hello | base64"));

system()不会将结果存储到数组a中,因为system()的工作是执行参数中提供的command并将其打印在控制台上,即stdout缓冲区中。在system的手册页中

  

system()通过调用执行command中指定的命令   /bin/sh -c          命令,并在命令完成后返回。

有一种方法可以解决该问题,即可以将其输出重定向到文件中,而不是在system()上打印stdout输出,然后从中读取文件并打印。例如

int main(void) {
        close(1); /* stdout file descriptor is avilable now */
        /* create the file if doesn't exist, if exist truncate the content to 0 length */
        int fd = open("data.txt",O_CREAT|O_TRUNC|O_RDWR,0664); /* fd gets assigned with lowest 
                                                  available fd i.e 1 i.e nowonwards stdout output 
                                                  gets rediredcted to file */
        if(fd == -1) {
                /* @TODO error handling */
                return 0;
        }
        system("echo Hello | base64"); /* system output gets stored in file */
        int max_char = lseek(fd,0,2);/* make fd to point to end, get the max no of char */
        char *a = malloc(max_char + 1); /* to avoid buffer overflow or 
                underflow, allocate memory only equal to the max no of char in file */
        if(a == NULL) {
                /* @TODO error handling if malloc fails */
                return 0;
        }
        lseek(fd,0,0);/* from beginning of file */
        int ret = read(fd,a,max_char);/* now read out put of system() from
                                          file as array and print it */
        if(ret == -1) {
                /* @TODO error handling */
                return 0;
        }
        a[ret] = '\0';/* \0 terminated array */
        dup2(0,fd);/*fd 0 duplicated to file descriptor where fd points i.e */
        printf("output : %s \n", a);
        /* to avoid memory leak, free the dynamic memory */
        free(a);
        return 0;
}

我上面的建议是一个临时解决方法,我不建议这样做,而是使用@chris Turner(http://man7.org/linux/man-pages/man3/popen.3.html)建议的[popen]

  

popen()函数通过创建管道,分叉,   和          调用外壳。根据定义,由于管道是单向的,因此          type参数只能指定阅读写作,不能同时指定两者;的          产生的流相应地为只读或只写。

例如

int main(void) {
        char buf[1024];
        FILE *fp = popen("echo Hello | base64","r");
        printf("%s\n",fgets(buf,sizeof(buf),fp));
        return 0;
}