提问人:Mohammed Ahmed 提问时间:10/1/2023 更新时间:10/1/2023 访问量:81
进程终止,信号 13 (SIGPIPE) 的默认动作
Process terminating with default action of signal 13 (SIGPIPE)
问:
我正在尝试在缓冲区中读取用户写入的全部数据,以在我自己的 shell“称为 hsh”中处理它,但该过程以信号 13 终止: 这是我传递给我的 shell 的命令:
valgrind echo " /bin/ls " | ./hsh
结果如下:
==203856== Process terminating with default action of signal 13 (SIGPIPE)
==203856== at 0x4960077: write (write.c:26)
==203856== by 0x48E0E8C: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1181)
==203856== by 0x48E17A7: new_do_write (fileops.c:449)
==203856== by 0x48E17A7: _IO_new_file_xsputn (fileops.c:1255)
==203856== by 0x48E17A7: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197)
==203856== by 0x48E037F: fputs_unlocked (iofputs_u.c:37)
==203856== by 0x10A7AE: ??? (in /usr/bin/echo)
==203856== by 0x4876082: (below main) (libc-start.c:308)
==203856==
==203856== HEAP SUMMARY:
==203856== in use at exit: 0 bytes in 0 blocks
==203856== total heap usage: 228 allocs, 228 frees, 25,267 bytes allocated
==203856==
==203856== All heap blocks were freed -- no leaks are possible
==203856==
==203856== For lists of detected and suppressed errors, rerun with: -s
==203856== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
以下是我读取数据的步骤:
- 使用 lseek 转到文件末尾并计算写入的字节数
- 再次使用 lseek 返回到文件的开头
- 为空字符分配一个缓冲区,其中包含此数量的数据 + 另一个字节
- 以块形式读取数据并将其存储在临时缓冲区中
- 将写入临时缓冲区的数据复制到实际缓冲区 但是,这种方法给了我一个信号 13(断管信号),我不知道为什么
这是我的代码: 注意:每个名称中带有 underscore(_) 的函数都在其他地方实现,其原型在“main.h”头文件中声明。
#include "main.h"
#define CHUNK_SIZE 1000
/**
* _getlines - Read the command lines
* @commands: The list where commands will be stored
* Return: On success - number of commands
* On error - "-1"
*/
int _getlines(char **commands)
{
char *line, *page, *chunk, ch, qoute;
ssize_t bytes_read, total_bytes_read = 0;
int j = 0, cmd_count = 0, i = 0, file_size;
line = malloc(CHUNK_SIZE * sizeof(char));
file_size = lseek(STDIN_FILENO, 0, SEEK_END);
lseek(STDIN_FILENO, 0, SEEK_SET);
page = malloc(file_size);
if (page == NULL)
return (-1);
while ((bytes_read = read(STDIN_FILENO, line, CHUNK_SIZE) > 0))
{
_strcpy(page + total_bytes_read, line);
total_bytes_read += bytes_read;
}
if (bytes_read == -1)
{
free(page);
return (-1);
}
printf("%s\n", page);
while (i < total_bytes_read)
{
ch = page[i++];
if (ch == '\"' || ch == '\'')
{
line[j++] = ch;
qoute = ch;
do {
ch = page[i++];
line[j++] = ch;
} while (ch != qoute);
}
else if (ch == '\n')
{
line[j++] = '\0';
commands[cmd_count] = _strdup(line);
j = 0;
(cmd_count)++;
}
else
line[j++] = ch;
}
if (cmd_count == 0)
{
commands[cmd_count] = _strdup(line);
cmd_count++;
}
free(line);
return (cmd_count);
}
答:
0赞
Fe2O3
10/1/2023
#1
虽然大部分代码整洁,但仍有许多问题需要解决。我砍掉了一些部分,专注于有问题的行。(顺便说一句。将超过 6000 个 SP 发送到您的代码中肯定会导致溢出,因为字符被复制到其 1000 字节长度。line
int _getlines(char **commands) // Unknown size of ptr array being populated
char *line, *page, *chunk, ch, qoute; // Illegible block of declarations. "chunk" is unused.
ssize_t bytes_read, total_bytes_read = 0;
int j = 0, cmd_count = 0, i = 0, file_size; // "sizes" should be unsigned
line = malloc(CHUNK_SIZE * sizeof(char)); // sizeof a char is 1. Don't multiply
// Missing verification of success
file_size = lseek(STDIN_FILENO, 0, SEEK_END); // Not needed
page = malloc(file_size); // Did you mean "file_size + 1"?
if (page == NULL)
return (-1); // What about the allocation of "line"?
_strcpy(page + total_bytes_read, line); // "line" is not a string!
if (bytes_read == -1) {
free(page); // What about the allocation of "line"?
while (i < total_bytes_read) { // have to scroll back to verify i starts at 0
if (ch == '\"' || ch == '\'') {
line[j++] = ch; // No verification the j < size of line[]
line[j++] = ch; // again, here
} while (ch != qoute);
else if (ch == '\n') {
commands[cmd_count] = _strdup(line); // unnecessary allocation (see below)
line[j++] = ch; // and again, here
}
if (cmd_count == 0) // Not sure about this...
{
commands[cmd_count] = _strdup(line); // line is NOT necessarily a C string
cmd_count++;
}
free(line); // finally... but what about "page"?
return (cmd_count); // return is not a function call. () unnecessary
有太多的烦恼需要“轻轻触摸”来纠正。
以下内容通过相当大的检修纠正了这些问题。这段代码至少有几条注释来解释它的操作。
int _getlines(char **commands, unsigned sz) { // array max size available
char k1024[ 1024 ], *page = NULL; // buffers here
ssize_t total = 0;
int i;
while( ( i = read( STDIN_FILENO, k1024, sizeof k1024 ) > 0 ) ) {
void *tmp = realloc( page, total + i + 1 ); // ongoing growth of input buffer
if( tmp == NULL ) {
// perhaps a diagnostic emitted here?
free( page );
return -1;
}
page = tmp;
memcpy( page + total, k1024, i );
total += i;
}
page[ total++ ] = 0; // terminate to form C string
i = 0;
while( isspace( page[ i ] ) ) i++; // toss away leading whitespace here
if( !page[ i ] ) {
free( page ); // that was a waste of time
return 0;
}
if( i )
memmove( page, page + i, total - i ); // shift everything to start of buffer
int cmd_count = 0;
commands[ cmd_count++ ] = page; // TODO: verify cmd_count doesn't exceed allowance
char qch = 0;
i = 0;
while( page[i] )
switch( page[i] ) {
case '\"':
case '\'':
if( !qch )
qch = page[ i ];
else if( page[ i ] == qch )
qch = 0;
i++;
break;
case '\n':
if( qch ) { i++; break; }
page[ i++ ] = 0;
if( page[ i ] )
commands[ cmd_count++ ] = page + i; // TODO: verify cmd_count
break;
default:
i++;
break;
}
return cmd_count;
}
调用方只需熄灭分配的整个块。(留给读者添加相关标题。free( commands[0] )
编辑
或...也许指向段的指针数组也是动态分配的!很难说,因为尚未提供调用此函数的代码。
评论
0赞
Mohammed Ahmed
10/1/2023
你没有使用lseek,为什么不需要它?
0赞
Fe2O3
10/1/2023
为什么不呢?因为这个版本读取“块”并将它们添加到不断增长的缓冲区中(注意:对 ...假设传入的数据是合理的(不是 47 Tb!!),则无需“预先分配”预期大小的缓冲区。realloc()
评论
_strcpy(page + total_bytes_read, line);
line
strcpy
read
str*
memcpy
bytes_read