0

我从只读 FIFO 读取几行时遇到问题。特别是,我必须读取两行——一个数字n,然后是一个\n和一个字符串str——我的 C 程序应该多次str写入只写 FIFO n。这是我的尝试。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

char *readline(int fd);

int main(int  argc, char** argv) {
    int in = open(argv[1], O_RDONLY);
    mkfifo(argv[2], 0666);
    int out = open(argv[2] ,O_WRONLY);
    char *line = (char *) malloc(50);
    int n;

    while (1) {
        sscanf(readline(in), "%d", &n);
        strcpy(line, readline(in));

        int i;
        for (i = 0; i < n; i++) {
            write(out, line, strlen(line));
            write(out, "\n", 1);
        }
    }

    close(in);
    close(out);
    return 0;
}

char *readline(int fd) {
    char *c = (char *) malloc(1);
    char line[50];

    while (read(fd, c, 1) != 0) {
        if (strcmp(c, "\n") == 0) { 
            break;
        }
        strcat(line, c);
    }
    return line;
}

该代码工作正常,但它在最后一个字符串重复之后放置了随机数量的换行符。此外,此数字在每次执行时都会更改。

有人可以给我任何帮助吗?

4

3 回答 3

1

除了读取字符和使用“字符串”比较来比较两个字符都远非有效之外,readline()返回一个指向声明为本地内存的指针readline(),即line[50]内存在返回后立即被释放readline(),因此访问它之后调用取消定义行为。

解决此问题的一种可能性是声明缓冲区以将行读入外部readline()并向下传递对它的引用,如下所示:

char * readline(int fd, char * line, size_t size) 
{
  if ((NULL != line) && (0 < size))
  {
    char c = 0;
    size_t i = 0;
    while (read(fd, &c, 1) >0) 
    {
      if ('\n' == c) or (size < i) { 
        break;
      }
      line[i] = c;
      ++i;
    }
    line [i] = 0;
  }

  return line;
}

然后这样称呼它:

char * readline(int fd, char * line, size_t size);

int main(void)
{
  ...
  char line[50] = "";
  ...
  ... readline(in, line, sizeof(line) - 1) ...
于 2013-11-09T18:08:20.250 回答
0

我没有尝试运行你的代码,但是在你的readline函数中你没有终止linewith null ( '\0') 字符。一旦你击中'\n'字符,你只需打破while循环并返回字符串line'\0'在从函数返回之前尝试添加字符readline

点击这里了解更多信息。

于 2013-11-09T17:43:28.343 回答
-1

你的代码在我的机器上不起作用,我想说你很幸运能得到任何有意义的结果。

以下是一些需要考虑的问题:

  • readline返回一个本地定义的静态字符缓冲区(line),该缓冲区将在函数结束时被销毁,并且它曾经占用的内存将可以被其他操作覆盖。
  • 如果line在分配时未设置为空字节,strcat则将其垃圾值视为字符,并可能在其结束后尝试写入。
  • 我怀疑你分配了一个 1 字节的缓冲区 ( c),只是因为你需要一个 char* in read。这是不必要的(参见下面的代码)。更糟糕的是,您没有在readline退出之前释放它,因此它会泄漏内存。
  • 循环将while(1)重新读取文件并将其重新打印到输出 fifo 直到时间结束。
  • 您正在使用一些“重型火炮” - 即strcat内存分配 - 有更简单的方法。
  • 最后,一些 C 标准版本可能要求您在使用之前声明所有变量。看到这个问题

这就是我修改您的代码的方式。请注意,如果第二行超过 50 个字符,则此代码也可能表现不佳。缓冲区限制有一些技术,但我在这个例子中没有使用任何技术:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

char *readline(int fd, char * buffer);

int main(int  argc, char** argv) {
    int in = open(argv[1], O_RDONLY);
    int out;
    int n;
    int i;
    char line[50];

    memset(line, 0, 50);
    mkfifo(argv[2], 0666);
    out = open(argv[2] ,O_WRONLY);

    sscanf(readline(in, line), "%d", &n);
    strcpy(line, readline(in, line));

    for (i = 0; i < n; i++) {
        write(out, line, strlen(line));
        write(out, "\n", 1);
    }

    close(in);
    close(out);
    return 0;
}

char *readline(int fd, char * buffer) {
    char c;
    int counter = 0;
    while (read(fd, &c, 1) != 0) {
        if (c == '\n') {
            break;
        }
        buffer[counter++] = c;
    }
    return buffer;
}

正如你所描述的,这适用于我的盒子。使用 GCC 4.8.2 编译。

于 2013-11-09T18:33:32.063 回答