我试图获取父进程中的字符串并将其传递给子进程,然后发送回一个字符串,根据passTest()方法声明其强度。它似乎正确地将字符串发送给子进程,但然后它表示在完成对子进程中接收的字符串的评估之前它在父进程上的读取条件失败。父母应该等孩子写,因为这不应该吗?
len = read(fd[P1_READ], val, tend);
非常感谢任何帮助
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
// Parent: reads from P1_READ, writes on P1_WRITE
// Child: reads from P2_READ, writes on P2_WRITE
#define P1_READ 0
#define P2_WRITE 1
#define P2_READ 2
#define P1_WRITE 3
#define NUM_PIPES 2
#define false 0 //Used for testing password strength
//Prototypes for other functions
char * passTest(char * password);
char * getPass(char * password);
int main(int argc, char *argv[])
{
int fd[2*NUM_PIPES];
int len, i;
char * val = malloc(100);
pid_t pid;
int tend;
// create all the descriptor pairs we need
for (i=0; i<NUM_PIPES; ++i)
{
if (pipe(fd+(i*2)) < 0)
{
perror("Piping Failed");
exit(EXIT_FAILURE);
}
}
//FORK ERROR
if ((pid = fork()) < 0)
{
perror("Fork Error");
return EXIT_FAILURE;
}
//child process
if (pid == 0)
{
// Child. CLOSE UNNEEDED FD
close(fd[P1_READ]);
close(fd[P1_WRITE]);
// used for output
pid = getpid();
// wait until parent sends a value
len = read(fd[P2_READ], val, tend);
if (len < 0)
{
perror("Child: Failed to read data from pipe\n");
exit(EXIT_FAILURE);
}
else if (len == 0)//In case nothing in pipe
{
fprintf(stderr, "Child: Read EOF from pipe\n");
}
else
{
// report what was recieved
printf("Child(%d): Received >%s<\n", pid, val);
val = passTest(val); //CHECK PASSWORD
tend = strlen(val);
printf("Child(%d): Sending >%s< back\n", pid, val);
if (write(fd[P2_WRITE], val, tend) < 0)
{
perror("Child: Failed to write response value");
exit(EXIT_FAILURE);
}
}
// finished. close remaining descriptors.
close(fd[P2_READ]);
close(fd[P2_WRITE]);
return EXIT_SUCCESS;
//END CHILD PROCESS
}else{
//PARENT PROCESS
// Close unused FD
close(fd[P2_READ]);
close(fd[P2_WRITE]);
// used for output
pid = getpid();
// send password to child
val = getPass(val);
strtok(val, "\n");
tend = strlen(val);
printf("Parent(%d): Sending %s to child\n", pid, val);
if (write(fd[P1_WRITE], val, tend) != tend)
{
perror("Parent: Failed to send value to child ");
exit(EXIT_FAILURE);
}
// now wait for a response
len = read(fd[P1_READ], val, tend);
if (len < 0)
{
perror("Parent: failed to read value from pipe\n");
exit(EXIT_FAILURE);
}
else if (len == 0)
{
// not an error, but certainly unexpected
fprintf(stderr, "Parent(%d): Read EOF from pipe\n", pid);
}
else
{
// report what we received
printf("Parent(%d): Received %s\n", pid, val);
}
// close descriptors
close(fd[P1_READ]);
close(fd[P1_WRITE]);
// wait for child termination
wait(NULL);
return EXIT_SUCCESS;
}
}//END MAIN
char * getPass(char * password){
printf("Please enter the password: ");
fgets(password, 50, stdin);
return password;
}
char * passTest(char * password){
printf("INSIDE passTest %s\n",password);
char * passStrength = "";
int i=0;
int found_lower = false, found_upper = false, found_number =false;
while(password[i] != '\0' || !(found_lower && found_upper&& found_number)) {
found_lower = found_lower || (password[i] >= 'a' && password[i] <= 'z');
found_upper = found_upper || (password[i] >= 'A' && password[i] <= 'Z');
found_number = found_number ||(password[i] >= '0' && password[i] <= '9');
i++;
}
if(found_lower && found_upper&& found_number){
strcpy(passStrength, "strong");
}else{
strcpy(passStrength, "weak");
}
if(strlen(password)<8){
strcpy(passStrength, "short");
}
printf("passStrength >%s<\n",passStrength);
return passStrength;
}
答案 0 :(得分:2)
我注意到的问题:
问题1
变量tend
未初始化。
我会改变
int tend;
到
int tend = 100; // Or anything else that makes sense in your application.
问题2
你有
char * passStrength = "";
然后继续使用
strcpy(passStrength, "strong");
肯定会导致未定义的行为。确保passStrength
中有足够的内存来保存要分配给它的值。
然后你使用:
return passStrength;
仅当passStrength
使用的内存超出函数调用时才会有效。你必须使用:
static char passStrength[100]; // Make it large enough.
或
char * passStrength = malloc(100);
问题3
在对write
的所有调用中,您发送的字符串没有终止空字符,例如:
tend = strlen(val);
printf("Parent(%d): Sending %s to child\n", pid, val);
if (write(fd[P1_WRITE], val, tend) != tend)
当您读取管道另一端的数据时,字符串将以空值终止。使用这些字符串就像它们是空终止字符串一样导致未定义的行为。您可以通过以下方式解决此问题:
再发一个字符。
if (write(fd[P1_WRITE], val, tend+1) != tend+1)
或
读取数据后添加空字符。
len = read(fd[P1_READ], val, tend);
val[len] = '\0';
问题4
while
语句passTest
未设置正确。因此,该函数访问超出有效范围的内存。这会导致未定义的行为。
将其更改为:
while( password[i] != '\0' && ( false == found_lower ||
false == found_upper ||
false == found_number ) ) {
我发现以下内容更容易理解:
while( password[i] != '\0' ) {
if ( found_lower && found_upper && found_number ) {
break;
}
found_lower = found_lower || (password[i] >= 'a' && password[i] <= 'z');
found_upper = found_upper || (password[i] >= 'A' && password[i] <= 'Z');
found_number = found_number ||(password[i] >= '0' && password[i] <= '9');
i++;
}