在向C子进程非常快速地写入大量数据时,我遇到了一个Broken Pipe错误。
所以我从python脚本运行一个c子进程:
process = subprocess.Popen("./gpiopwm", stdin=subprocess.PIPE)
while True:
process.stdin.write("m2000\n")
print "bytes written"
gpiopwm.c主循环的确定:
printf("1\n");
while (1) {
fgets(input,7,stdin); // Takes input from python script
printf("2\n");
numbers = input+1; // stores all but first char of input
char first = input[0]; // stores first char of input
if (first=='m') {
printf("3\n");
printf("%s\n",numbers);
}
}
但是,此输出如下:
1
bytes written
Traceback (most recent call last):
File "serial-receive-to-pwm.py", line 20, in <module>
process.stdin.write("m2000\n")
IOError: [Errno 32] Broken pipe
C程序显然在fgets
行中断,因为永远不会打印2
。
我做错了什么?我怎么能避免这个?
编辑:
我已经更新了fgets
行,因此它不包含dereference参数,但仍然会收到管道错误。
编辑:
input
初始化为char *input="m2000";
答案 0 :(得分:2)
如果您尝试从控制台运行C程序,您将看到它崩溃。如果你在调试器中运行,你会发现它在这一行:
fgets(*input,7,stdin);
似乎input
是一个字符数组,当你用*input
取消引用时,你传递的不是指针而是一个char
值。这会导致未定义的行为和崩溃。
如果不是错误,该行应该给你,然后是来自编译器的非常大的警告消息。不要忽视警告信息,它们通常表明你做错了什么并且可能很危险。
一般提示:在开发应该从其他程序调用的程序时,就像在此处一样, test 程序首先确保程序正常运行。如果它不起作用,请先修复它。
最后提示:请记住,fgets
包含目标字符串中的换行符。您可能需要检查它并将其删除(如果有的话)。
使用上一次编辑,显示input
的声明我们知道真正的问题:您正在尝试修改常量数据,并且您还希望超出界限数据也是如此。
当您使input
指向文字字符串时,您必须记住所有文字字符串都是只读,您无法修改文字字符串。尝试这样做是未定义的行为。更糟糕的是,你的字符串只有六个字符长,但你试着写七个字符。
首先更改input
的声明和初始化:
char input[16] = "m2000\n";
这会将它声明为一个数组,位于堆栈上并且可以修改。然后做
while (fgets(input, sizeof(input), stdin) != NULL) { ... }
这完成了两件事:首先使用sizeof(input)
作为大小,你可以确定fgets
永远不会写出界限。其次,通过在循环条件中使用fgets
调用,循环将在Python脚本中断时结束,并且您将永远不会循环读取任何内容,然后处理您从未读过的数据。< / p>