gpt4 book ai didi

c++ - 在 SFML 中使用 TcpSocket 发送数据导致段错误

转载 作者:行者123 更新时间:2023-11-28 01:19:47 30 4
gpt4 key购买 nike

我正在使用 SFML 的 TcpSocket 类来发送和接收数据,但由于某种原因,我一直收到错误 Segmentation fault: 11。这是服务器类:

#include "ServerGame.hpp"

ServerGame::ServerGame()
{

}

void ServerGame::sendData(char data[3][3])
{

if (client.send(data, 9) != sf::Socket::Done)
{
//std::cout << "error" << std::endl;
}

}

void ServerGame::connect()
{
sf::TcpListener listener;

// bind the listener to a port
if (listener.listen(666) != sf::Socket::Done)
{
std::cout << "error" << std::endl;
}

// accept a new connection
if (listener.accept(client) != sf::Socket::Done)
{
std::cout << "error" << std::endl;
}
}

char** ServerGame::receiveData()
{
char **data;
data = new char*[3];
for(int i = 0; i < 3; ++i)
{
data[i] = new char[3];
}
std::size_t received;

// TCP socket:
if (client.receive(data, 9, received) != sf::Socket::Done)
{
// error...
}
return data;
}

这是客户端类:

#include "ClientGame.hpp"
#include <iostream>

ClientGame::ClientGame()
{

}

void ClientGame::connect()
{
sf::Socket::Status status = socket.connect("127.0.0.1", 666);
if (status != sf::Socket::Done)
{
// error...
}
}

void ClientGame::sendData(char data[3][3])
{
if(socket.send(data, 9) != sf::Socket::Done)
{
//error...
}
}

char** ClientGame::receiveData()
{
char **data;
data = new char*[3];
for(int i = 0; i < 3; ++i)
{
data[i] = new char[3];
}
std::size_t received;
if (socket.receive(data, 9, received) != sf::Socket::Done)
{
std::cout << "error" << std::endl;
}
return data;
}

这是启动服务器和发送数据的主类:

#include "ServerGame.hpp"
#include "ClientGame.hpp"
int main()
{
ServerGame sg;
sg.connect();
char arr[3][3] =
{
{'a', 'b', 'c'},
{'d', 'e', 'f'},
{'g', 'h', 'i'}
};
sg.sendData(arr);

}

这是启动客户端和接收数据的主类:

#include "ClientGame.hpp"

int main()
{
ClientGame cg;
cg.connect();
char** arr = cg.receiveData();
std:: cout << arr[0][0] << std::endl;
}

我首先编译并运行服务器类,然后对客户端类执行相同的操作。当我尝试访问我发送的字符数组的第一个元素时,它给出了一个段错误。为什么会这样?

最佳答案

一个问题是假设 char**char 的二维数组相同。它们相同。

当你这样做时:

char **data;
data = new char*[3];
for(int i = 0; i < 3; ++i)
{
data[i] = new char[3];
}

您不是使用连续数据布局动态创建二维 char 数组,类似于 char[3][3]。内存布局可能看起来像这样:

data[0] ->  0x32181000
data[1] -> 0x321A9760
data[2] -> 0x321AC980

换句话说,行散布在整个堆内存中,并且不连续。

因此当你调用这个函数时:

if (socket.receive(data, 9, received) != sf::Socket::Done)

socket.receive 函数需要一个 9 字节的连续缓冲区,但您没有提供它。 receive 函数很可能会覆盖第一行,最多 6 个字节从第一行的边缘掉落(第一行被分配为只有 3 个字节),因此溢出到内存中导致段错误。


我认为问题源于您试图将二维数组从一个函数传递到另一个函数,并使用 char** 代替实际的二维数组而犯了错误。

为了在不引入指针的情况下使事情变得更简单,创建一个包含二维 char 数组的struct,然后在函数之间传递这个结构。

struct char2D
{
char myArray[3][3];
};

然后代替 char **,只使用 char2D 的实例,并在需要时引用内部数组。

例如:

char2D ClientGame::receiveData()
{
char2D data;
std::size_t received;
if (socket.receive(&data.myArray[0][0], 9, received) != sf::Socket::Done)
{
std::cout << "error" << std::endl;
}
return data;
}

然后在 main 中:

int main()
{
ClientGame cg;
cg.connect();
char2D arr = cg.receiveData();
std:: cout << arr.myArray[0][0] << std::endl;
}

这样做的原因是 struct 是可复制和可赋值的。因此,每当您按值传递并按值返回时,内部数组都会被复制。

关于c++ - 在 SFML 中使用 TcpSocket 发送数据导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57023655/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com