c - 分段错误 - 套接字编程 - C
问题描述
我正在尝试用 C 编写一个回显服务器\客户端模型。我的代码编译但在运行时抛出了分段错误错误[我相信服务器端进程]。在 CLion 调试环境中进行测试时,服务器进程能够执行 accept() 系统调用并进入等待状态,直到客户端连接。因此,我认为分段错误错误发生在客户端进行 connect() 系统调用之后。
以下是相关的代码片段(仅最后一部分 - 不是完整的程序):
/* [6] LISTEN FOR CONNECTIONS ON BOUND SOCKET===================================================================== */
struct sockaddr_storage ample; /* from Beej Guide 5.6 accept() */
socklen_t ample_sz = sizeof(ample);
fd_activeSock = accept(fd_listenSock, (struct sockaddr *)&established_SERV_param, &le_sz);
if (fd_activeSock == -1) /* Error checking */
{
fprintf(stderr, "\nNo forum for communication...\nTERMINATING PROCESS");
exit(EXIT_FAILURE);
}
printf("\nCommunication Established! What's your sign??");
freeaddrinfo(established_SERV_param); /* free up memory */
/* [7] ACCEPT A CONNECTION (BLOCKING)============================================================================= */
/* MAIN LOOP====================================================================================================== */
while(1)
{
bzero(msg_incoming, 16);
recv(fd_activeSock, msg_incoming, 16, 0);
printf("%s", msg_incoming);
send(fd_activeSock, msg_incoming, 16, 0);
}
当我在不同的终端中运行这两个程序时(当然首先是服务器进程),在错误之前运行的最后一个打印语句是:
printf("\nCommunication Established! What's your sign??");
错误输出到服务器终端。有一个核心转储;对于未来的问题,有人可以建议一个关于梳理核心转储文件的初学者教程。此外,我已经在注释掉 freeaddrinfo() 调用的情况下运行代码,但仍然收到分段错误错误,所以我不认为这是问题所在。为什么要运行它?我不想要内存泄漏。谢谢您的帮助。
解决方案
recv()没有在缓冲区的末尾显式放置一个空终止符,但printf()
需要一个。
在声明中:
bzero(msg_incoming, 16);
recv(fd_activeSock, msg_incoming, 16, 0);
printf("%s", msg_incoming);
尽管msg_incoming
已被归零,但在recv
调用中填充它时,如果填充了所有 16 个元素,则不能保证数组的最后一个元素填充了 '\0',从而将缓冲区保留为非空终止数组。如果发生这种情况,则在printf()
调用时可能会出现段错误。或者更糟糕的是,可能不会发生段错误,导致您相信您的代码可以正常工作。(又名未定义的行为)
修复方法是检查recv()的返回值:
ssize_t bytes = recv(fd_activeSock, msg_incoming, 16, 0);
if(bytes <= 0)
{
//handle error/end of message condition
}
else
{
msg_incoming[bytes] = '\0';
printf("%s", msg_incoming);
}
有关使用套接字读取数据的附加材料。
推荐阅读
- ios - AFNetworking 3.0 AFHTTPSessionManager 使用 NSURLRequest
- html - 如何并排制作带有图像和文本的部分
- java - Spring Boot,在 REST 响应中将日期时间精度定义为毫秒
- javascript - Javascript循环以错误的顺序执行
- java - 在 LinearLayout 中以相反的顺序添加视图
- javascript - 如何在反应中强制重新加载和清除最近更新的缓存
- mysql - .Net 连接字符串连接 MySQL localhost 没有密码
- python - 如何绘制熊猫数据框的每一列?
- yql - 通过 HTTP POST 和 PUT 方法批量插入/更新 Vespa 文档
- reactjs - FontAwesome SCSS Tree-Shaking