c++ Sockets -客户端给出分段错误(linux)
C++ Sockets - Client gives segmentation fault (linux)
我创建了一个服务器/客户机连接。服务器和客户端都编译正确,但当我运行客户端,它给我一个Segmentation Fault (core dumped)
我不知道我做错了我的内存分配。程序没有挂起什么的。我认为我的程序正在写入内存的只读部分,或者可能正在访问不可用的内存。
如果有人能告诉我bug在哪里,我将非常感激。
client.cpp
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int main() {
char a;
int client;
int portNum = 1500;
int bufsize = 1024;
char* buffer = new char (bufsize);
bool isExit = false;
char* ip;
strcpy(ip, "127.0.0.1");
struct sockaddr_in direc;
if ((client = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
cout << "Error creating socket..." << endl;
exit(0);
}
cout << "Enter # to end call" << endl;
cout << "ttt[s] to begin with" << endl;
cin >> a;
cout << "Socket created successfully..." << endl;
direc.sin_family = AF_INET;
direc.sin_port = htons(portNum);
inet_pton(AF_INET, ip, &direc.sin_addr);
if (connect(client,(struct sockaddr *)&direc, sizeof(direc)) == 0)
cout << "Connection to the server " << inet_ntoa(direc.sin_addr) << endl;
cout << "Awaiting confirmation from the server..." << endl;
recv(client, buffer, bufsize, 0);
cout << "Response received: " << buffer;
cout << "nRemember to put an asterisk at the end to send a message * n Enter # to terminate the connection" << endl;
do {
cout << "Enter a message: ";
do {
cin >> buffer;
send(client, buffer, bufsize, 0);
if (*buffer == '#') {
send(client, buffer, bufsize, 0);
*buffer = '*';
isExit = true;
}
} while (*buffer != 42);
cout << "Mensage received: ";
do {
recv(client, buffer, bufsize, 0);
cout << buffer << " ";
if (*buffer == '#') {
*buffer = '*';
isExit = true;
}
} while (*buffer != 42);
cout << endl;
} while (!isExit);
cout << "Connection terminated. END PROGRAMnn";
close(client);
return 0;
}
我假设您不需要server.cpp,因为它都很好,正在等待传入的连接。
谢谢!
这段代码有很多问题,但最直接和最致命的错误是:
int bufsize = 1024;
char* buffer = new char (bufsize);
分配1个字符,并尝试将bufsize
的值存储在其中。bufsize
太大了,所以它被截断为0。最终结果是,缓冲区指向单个字符,而不是1024的数组,并且该单个值被设置为0。当您尝试将bufsize
字节读入缓冲区时,几乎肯定会超出该单个字符,并且行为是未定义的。最有可能的是,它要么破坏其他程序数据(并可能在以后引起问题),要么写入无效内存并立即崩溃。
我相信你是指
int bufsize = 1024;
char* buffer = new char[bufsize];
相反,char buffer[1024];
做你想做的事。用sizeof(buffer)
代替bufsize
。此外,以下语句通常更可取:
在文件的顶部,就在include下面:
#define BUFSIZE 1024
和
char buffer[BUFSIZE];
现在您可以使用BUFSIZE
或sizeof(buffer)
。两者都在编译期间解决,因此没有性能成本。
2018附录:
constexpr int BUFSIZE = 1024;
将在现代c++ (c++ 11或更新版本)中具有相同的效果,并且没有#define
宏替换的缺点。
这两个选项的优点是内存是自我管理的。char* buffer = new char[bufsize];
需要在代码中的某个地方有一个delete[] buffer
来放回内存。你必须确保到达delete[]
防止泄漏。除非迫不得已,否则不要使用指针和动态分配。
,
char* ip;
strcpy(ip, "127.0.0.1");
分配一个未初始化的指针ip
。最有可能的是,if包含的地址是由堆栈上发生的任何垃圾组成的,并且不指向有效的char
数组。然后"127.0.0.1"写在ip
所指向的任何地方。
同样,我们确切地知道ip
将指向什么,因此修复很容易:
char * ip = "127.0.0.1";
我喜欢
char ip[] = "127.0.0.1";
但是我没有理由这样做。
2018附录:我现在有理由这样做了。char * ip = "127.0.0.1";
在现代c++中是完全非法的。字符串字面值是常量数组,如果使用非常量指针修改字符串字面值,则将它们赋值给非常量指针可能会导致很多问题。在过去,我们只是忽略这个问题,从不按字面意思写信。除非您稍后进行了一些抽象,并花费了数天或数周的时间进行调试。最好在源代码处解决问题,并将文本复制到可变数组(如果它有可能发生变化)。如果可以的话,最好在整个代码中保持const正确。
recv(client, buffer, bufsize, 0);
有两个问题:
丢弃读取的字节数和返回的错误码。由于套接字错误,程序根本不知道它是否读取了任何内容,或者它获得了整个消息、消息的一部分或消息的更多内容。
它还显示了对TCP如何工作的误解。TCP不能在良好的、定义好的消息中工作。写入套接字的数据可能与其他消息一起打包到同一个出站数据包中。它可能被分割成多个数据包,这些数据包将在不同时间到达。这背后的逻辑超出了StackOverflow的范围。读一些TCP和流数据
但等等!还有更多!
cin >> buffer;
如果用户输入1024或更多字符,即使固定到预期的大小,也会溢出buffer
(不要忘记需要null终止符)。此外,如果不自己计数,您就不知道输入了多少字符。痛苦而缓慢。幸运的是,有std::string
。
std::string outbuf;
cin >> outbuf;
一次性解决了两个问题。它调整自己的大小,并对其内容进行计数。整洁的,是吧?
send(client, buffer, bufsize, 0);
将发送1024字节的数据,即使用户输入更少。或者更多。讨厌的东西。使用上面的输出,
send(client, outbuf.c_str(), outbuf.length(), 0);
每次写入正确的字符数,但如果您想保留字符串的结束null,则必须发送outbuf.length() + 1
字符。
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- 这些是什么样的错误?即使我不在 Linux 上工作,我也遇到了 Linux 错误
- Arch Linux.AUR 包 mysql 不能用 makepkg 构建.错误:构建 () 中出现故障
- 分段 Linux Ubuntu 中的 g++ 错误,但在 Windows 中的 g++/MingW 中,在 C++ 中打
- [longjmp/setjmp]c++ 相同的代码窗口有异常 Linux 没有错误并且运行良好
- 在 Linux 中使用 -fvisibility=hidden 编译时出现库加载错误
- g++ 9.2.1 (Linux) 会导致 seg 错误,但 Windows 上的代码块不会
- 调试模板时出现问题.专门针对 Linux GCC 7、GCC 6、GCC 5、GCC 4.9 错误构建失败:模板参数 1
- LINUX 操作系统上的错误:令牌之前预期的构造函数、析构函数或类型转换'('?
- 从 Linux OMI (omicli) 到 Windows WMI 的连接失败,并出现与 DMTF 相关的错误
- C++ Linux 运行时basic_string::_M_construct null 无效错误
- Stringstream编译错误仅发生在linux环境中
- 如何在长g++错误消息上使用linux less命令
- curl_easy_在Linux上执行分段错误
- 在linux上使用g++输出错误,在windows上更正
- C++新手,得到编译错误(Linux,G ++编译器)
- Android NDK示例构建错误linux
- 共享内存的std::string给分割错误(linux)
- c++ Sockets -客户端给出分段错误(linux)
- C++提升日志记录编译错误 (Linux)