[英]Strncmp: Unusual segmentation Fault
我真的是C语言的新手,但是我已经有一段时间写C ++了。 我正在编写一个客户端服务器聊天程序。 输入用户名后,我需要在会话开始时用几个不同的选项提示用户。 最初,我尝试使用getchar()函数,但是由于某种原因,以下模式的任何语句都不会产生预期的结果:
int x = getchar();
if (x == '2') doSomething();
如果用户输入2,它将永远不会转到“ doSomething”区域。 因此,我尝试使用fgets和strncmp代替。 但是现在,我在strncmp上一直遇到分段错误。 这是代码中最相关的部分,其中一些注释是我尝试使用getchar的部分。 诚然,这有点混乱,因为我只是将其作为一个测试而抛出。 我认为也许为字符串分配额外的空间将有助于防止seg错误,但当然没有。
for( ; ; )
{
printf("\r\n1.List Users \r\n2.Chat \r\n3.Exit \r\n \r\n \r\n");
char *x = malloc(5);
fgets(x, 2, stdin);
if (x[0] != NULL)
{
if (strncmp (x[0],"a",1) == 0)
{
printf("yay");
}
}
/* int x = getchar();
if(x == 'a') // Compare input to 'q' character
break;
fprintf(stdout, "%d\n", x);*/
/*x = c - '0';
if (x == 1)
getUsers(sockfd);
if ( x == 2 )
{
pthread_create(&sndThread, NULL, do_send, (void *) sockfd);
pthread_create(&rcvThread, NULL, do_recv, (void *) sockfd);
pthread_join(sndThread, NULL);
pthread_join(rcvThread, NULL);
}
if ( x == 3 )
{
close(sockfd);
exit(0);
}*/
}
您可以在剩余的注释中看到尝试执行操作的剩余部分,例如使用减法将char转换为int。 这来自我在互联网上找到的东西。 我还在互联网上听说getchar在输入缓冲区中保留\\ n。
因此,这是我为客户提供的全部代码,因此可以将其放在上下文中:
int main(int argc, char **argv)
{
int sockfd, i;
char *myName = malloc(MSGSIZE);
char c;
struct sockaddr_in servaddr;
int status;
pthread_t sndThread;
pthread_t rcvThread;
if(argc != 2)
{
printf("Error: expected IP address argument");
exit(1);
}
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
error("Socket error");
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORTNUM);
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <=0)
{
printf("inet_pton error for %s \n", argv[1]);
exit(3);
}
if(connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
{
error("Connect error");
}
printf("Type in a username: \r\n");
while ( fgets(myName[i],MSGSIZE,stdin ) == NULL){}
printf(">%s<\n",myName);
send_userName(myName,sockfd);
for( ; ; )
{
printf("\r\n1.List Users \r\n2.Chat \r\n3.Exit \r\n \r\n \r\n");
char *x = malloc(5);
fgets(x, 2, stdin);
if (x[0] != NULL)
{
if (strncmp (x[0],"a",1) == 0)
{
printf("yay");
}
}
/* int x = getchar();
if(x == 'a') // Compare input to 'q' character
break;
fprintf(stdout, "%d\n", x);*/
/*x = c - '0';
if (x == 1)
getUsers(sockfd);
if ( x == 2 )
{
pthread_create(&sndThread, NULL, do_send, (void *) sockfd);
pthread_create(&rcvThread, NULL, do_recv, (void *) sockfd);
pthread_join(sndThread, NULL);
pthread_join(rcvThread, NULL);
}
if ( x == 3 )
{
close(sockfd);
exit(0);
}*/
}
}
x[0]
是一个字符,但x
是char*
。 strncmp
应该仅将x
用作参数,而不是x[0]
。 也就是说,你不想
strncmp(x[0],"a",1)
反而
strncmp(x,"a",1)
另外,如果您确实想强调您是从x
的第一个字符开始的,则可以执行以下任一操作:
strncmp(x+0,"a",1)
strncmp(&x[0],"a",1)
getchar()
的行为取决于终端的模式。 大多数操作都在“煮熟”模式下进行,这意味着在输入整行(并按Enter键)后, getchar()
将返回。 终端这样做是为了允许进行行编辑。 要使getchar()
立即返回,您需要将其切换为“原始”模式。
接下来,您应该启用所有编译器警告,因为它会告诉您上面的代码出了什么问题:
strncmp()
期望将char*
作为第一个参数,但您传递了char
。 这意味着代码将从任意内存中读取。
x[0] != NULL
也没有意义(将字符与空指针进行比较)。 要知道fgets()
是否未返回任何内容,请查看其返回代码。
char * success = fgets(x, 2, stdin);
if(success == null) { ... error handling... }
if (strncmp (x,"a",1) == 0) {
printf("yay");
}
从完整的源代码中删除#include
行通常通常无济于事。 如果我想编译您的代码,那么现在我不得不花几分钟来将它们组合在一起。 浪费时间。
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MSGSIZE 100
#define PORTNUM 12
#define SA struct sockaddr
void error(const char *);
void send_userName(const char *, int);
因此,如果添加这些标头,并尝试编译您的代码,则会收到一些严重的可怕警告。 让我们看一看警告。
在此类中,您可以将变量传递给正在寻找其他类型变量的函数。
foo.c:59:19: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'char *'; take the address with & [-Wint-conversion]
while ( fgets(myName[i],MSGSIZE,stdin ) == NULL){}
^~~~~~~~~
&
/usr/include/stdio.h:236:30: note: passing argument to parameter here
char *fgets(char * __restrict, int, FILE *);
^
foo.c:74:18: warning: comparison between pointer and integer ('int' and 'void *')
if (x[0] != NULL)
~~~~ ^ ~~~~
foo.c:77:26: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Wint-conversion]
if (strncmp (x[0],"a",1) == 0)
^~~~
&
/usr/include/string.h:84:26: note: passing argument to parameter here
int strncmp(const char *, const char *, size_t);
^
第二类是使用未初始化变量的位置:
foo.c:59:26: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
while ( fgets(myName[i],MSGSIZE,stdin ) == NULL){}
^
foo.c:18:18: note: initialize the variable 'i' to silence this warning
int sockfd, i;
^
= 0
您应该真正尝试解决这些问题,因为否则代码将被破坏。 如果您不明白为什么会发出特定警告,则应对此进行询问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.