-1

我试图通过从管道中读取字符然后将它们放入结果字符串来实现合并。我不断收到分段错误,并且无法调试问题的根源。当我删除对该函数的调用时,问题就消失了,所以我觉得这里有些不正确:

MAX_LENGTH 设置为 1024,我只对大约 30 个字符进行排序,所以我相信我应该有多余的空间。

int merge(char *result, int *leftpipefd, int *rightpipefd) {
char left[MAX_LENGTH/2];
char right[MAX_LENGTH/2];
int leftpos = 0;
int rightpos = 0;
int resultpos = 0;

read(leftpipefd[READ_END], left, MAX_LENGTH/2);
read(rightpipefd[READ_END], right, MAX_LENGTH/2);

int leftlen = strlen(left);
int rightlen = strlen(right);

while (leftpos < leftlen || rightpos < rightlen) {
    if (leftpos < leftlen && rightpos < rightlen) {
        if (left[leftpos] <= right[rightpos]) {
            result[resultpos] = left[leftpos];
            resultpos++;
            leftpos++;
        } else {
            result[resultpos] = right[rightpos];
            resultpos++;
            rightpos++;
        }
    } else if (leftpos <  leftlen) {
        result[resultpos] = right[rightpos];
        resultpos++;
        rightpos++;
    } else if (rightpos <  rightlen) {
        result[resultpos] = left[leftpos];
        resultpos++;
        leftpos++;
    }
}

return EXIT_SUCCESS;
}

谁能看到我做错了什么?

4

2 回答 2

0

如果您将 N 个字符读入长度为 N 的缓冲区,您如何期望该strlen函数正常工作……它至少需要一个缓冲区,N+1因为必须有空间容纳终止\0字符。当那不存在时,谁知道接下来会发生什么……

于 2013-02-13T02:22:28.770 回答
0

几件事...

来自http://linux.die.net/man/2/read ...

read() 尝试将文件描述符 fd 中的 count 个字节读入缓冲区,从 buf 开始。如果 count 为零,则 read() 返回零并且没有其他结果。如果 count 大于 SSIZE_MAX,则未指定结果。

MAX_LEN 是什么?是否大于 SSIZE_MAX?如果是这样,您有未定义的行为。

如果 read()s 没有输入,您将不会读取任何内容......并且您尚未初始化的缓冲区将不会更改。您应该初始化缓冲区。

从同一页...

出错时,返回 -1,并适当设置 errno。

如果读取失败,您的缓冲区仍未定义/未初始化,但您不会检测/处理这种情况。您需要在 read() 之后立即使用一些错误处理代码。

此外,在同一个手册页上,没有迹象表明您的 read() 缓冲区是空终止的。正如 Floris 指出的那样,这意味着您的 strlen()s 可能会在分配的缓冲区结束后继续读取。

而 (leftpos < leftlen || rightpos < rightlen) {

此行可能有误。如果 leftpos >= leftlen 但 rightpos < rightpos 你将进入 while 块的主体。您可能会以这种方式开始访问无效内存。你真的需要&&吗?

于 2013-02-13T02:22:53.250 回答