Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;套接字-客户端给出分段错误(linux)_C++_Linux_Sockets_Memory - Fatal编程技术网

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

C++ C++;套接字-客户端给出分段错误(linux),c++,linux,sockets,memory,C++,Linux,Sockets,Memory,我创建了一个服务器/客户端连接。服务器和客户端都正确编译,但当我运行客户端时,它会给我一个分段错误(内核转储) 我不知道我的内存分配有什么问题。程序没有悬空或任何东西。我认为我的程序正在写入内存的只读部分,或者可能正在访问不可用的内存 如果有人能告诉我bug在哪里,我会非常感激 client.cpp #include <iostream> #include <string.h> #include <sys/types.h> #include <sys/s

我创建了一个服务器/客户端连接。服务器和客户端都正确编译,但当我运行客户端时,它会给我一个
分段错误(内核转储)

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

如果有人能告诉我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 << "\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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
字符a;
int客户端;
int-portNum=1500;
int bufsize=1024;
char*buffer=新字符(bufsize);
bool-isExit=false;
字符*ip;
strcpy(ip,“127.0.0.1”);
direc中的结构sockaddr_;
if((客户端=套接字(AF_INET,SOCK_STREAM,0))<0){

cout此代码存在许多问题,但直接和致命的错误是:

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]; 
现在您可以使用
BUFSIZE
sizeof(buffer)
。这两种方法都是在编译过程中解决的,因此没有性能成本

2018年附录:

constexpr int BUFSIZE = 1024;

在现代C++(C++ 11或更新版)中具有相同的效果,并且没有从“代码>定义< <代码> >宏/宏>的下限。 这两个选项的优点是内存都是自我管理的。

char*buffer=new char[bufsize];
需要在代码中的某个地方使用
delete[]buffer
将内存放回。并且您必须确保达到
delete[]
以防止泄漏。除非必要,否则不要使用指针和动态分配

其次,

分配一个未初始化的指针,
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++中,是不合法的。字符串字是常数数组,如果指针被用来修改字符串文字,那么将它们分配给非常量指针会导致很多不良。在旧的日子里,我们忽略了这个问题,从来没有给文字写过。除了后来做了一些抽象,花了几天或几周的时间。ebugging。如果可能会发生变异,最好在源代码处切断问题,并将文本复制到可变数组中。如果可以,最好在整个代码中保留

接下来,

recv(client, buffer, bufsize, 0);
有两个问题:

它丢弃读取的字节数和返回的错误代码。程序不知道是否由于套接字错误读取了任何内容,或者是否获得了整个消息、部分消息或更多消息

这还表明了对TCP工作原理的误解。TCP在定义良好的消息中不起作用。写入套接字的数据可能与其他消息一起打包到同一个外绑定数据包中。它可能被拆分为多个在不同时间到达的数据包。这背后的逻辑超出了StackOverflow的范围。请重新考虑对TCP和流式数据进行加密

但是等等!还有更多

cin >> buffer;
如果用户键入1024个或更多字符(不要忘记需要空终止符),即使将缓冲区固定为预期大小,也会溢出
缓冲区。此外,如果不亲自计算,您不知道输入了多少个字符。痛苦而缓慢。幸运的是
std::string

std::string outbuf;
cin >> outbuf;
一次就解决了这两个问题。它调整了自身大小并记录了内容。整洁,嗯

send(client, buffer, bufsize, 0);
将发送1024字节的数据,即使用户键入更少或更多。糟糕。使用上面的EXPUFF

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

每次写入正确数量的字符,但如果要保留字符串的终止null,则必须发送
extuf.length()+1
个字符。

char*ip;strcpy(ip,“127.0.0.1”);
从不为指向的指针分配任何存储空间,从不将其指向任何对象,然后将数据复制到未定义的区域中。KABOOOM!…并且
char*buffer=new char(bufsize);
与您的想法不符(
()[
)。您正好有0个
delete[]
我不知道我的内存分配出了什么问题。
一切。任何地方都没有正确的分配。为什么不直接为该缓冲位写入
char*ip=“127.0.0.1”
同上。大小是已知的,所以只需
char buffer[1024]
cin>>缓冲区;
如果用户键入的字符超过1024个,该怎么办?
send(client,buffer,bufsize,0);
只是编写了整个缓冲区,而不仅仅是用户键入的内容。哇,这就是我所说的详细而详尽的答案。+1,完全值得!
send(client, outbuf.c_str(), outbuf.length(), 0);