繁体   English   中英

C++ 套接字 - 客户端给出分段错误 (linux)

[英]C++ Sockets - Client gives segmentation fault (linux)

我创建了一个服务器/客户端连接。 服务器和客户端都正确编译,但是当我运行客户端时,它给了我一个Segmentation Fault (core dumped)

我不知道我的内存分配做错了什么。 该程序没有悬空或任何东西。 我认为我的程序正在写入内存的只读部分,或者可能访问不可用的内存。

如果有人能告诉我错误在哪里,我将不胜感激。

客户端

#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 << "\t\t\t[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 PROGRAM\n\n";
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 此外,以下通常更可取:

在文件的顶部,就在包含的下面:

#define BUFSIZE 1024

进而

char buffer[BUFSIZE]; 

现在您可以使用BUFSIZEsizeof(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 contains 由堆栈上的任何垃圾组成,并且不指向有效的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固定为预期大小,也会溢出buffer 此外,您不知道输入了多少字符而不自己计算它们。 痛苦而缓慢。 幸运的是有std::string

std::string outbuf;
cin >> outbuf;

一次解决这两个问题。 它会调整自身大小并对其内容进行计数。 整洁吧?

send(client, buffer, bufsize, 0);

即使用户输入较少,也将发送 1024 字节的数据。 或者更多。 哎呀。 从上面使用outbuf,

send(client, outbuf.c_str(), outbuf.length(), 0);

每次写入正确数量的字符,但如果您想保留字符串的终止空值,则必须发送outbuf.length() + 1字符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM