如何在设置元素中重用向量?

How to re-use vector with set elements?

本文关键字:向量 元素 设置      更新时间:2023-10-16

所以我正在使用我的程序将我的Rasperry Pi相机流式传输到我的计算机上。下面列出的矢量给我带来了问题。在大约 30 秒的流媒体播放后,它让我std::bad_alloc。有没有办法在循环中一遍又一遍地重用这个向量(例如调整大小,清除)? 以下是简化的代码:

while(isRunning)
{
recv(Connection, received_message, sizeof(received_message), NULL); //receiving the size of image in bytes
fileSize = atoi(received_message);
std::vector<char> fileData(fileSize); //<- this vector is giving me problems
recv(Connection, &fileData[0], CHUNK_SIZE, 0); //Receiving the image
//The code loops over and over again
}

TCP 是一种流协议。它没有消息的概念。在连接的一端写入 10,000 字节并不意味着所有 10,000 字节都将到达接收器并同时可用。

因此,recv与现有的东西一起工作。它返回当前可用的任何内容,如果没有可用,recv等待数据可用。这意味着,如果您要求 10,000 字节,您可能会完全根据网络堆栈的心血来潮获得 1 字节到 10,000 字节之间的任何字节,一个 IP 数据包中可以传输的最大数据量,以及太多其他变量无法列出。

所以

recv(Connection, received_message, sizeof(received_message), NULL);

可能会在收到所有received_message之前返回。fileSize将从错误的输入中计算,很可能是一个不以 null 结尾的字符串,并且在缓冲区末尾运行,触发未定义的行为,垃圾输入会发出垃圾。

然后,此不正确的fileSize用于调整vector的大小,现在几乎可以肯定是错误的大小。如果太小,

recv(Connection, &fileData[0], CHUNK_SIZE, 0);

可能会在vector结束时流出更多未定义的行为。如果存储太大,系统可能无法为vector分配存储,因为没有足够的连续存储可用。这似乎是OP发生的事情。

解决方案:循环所有调用recv,直到到达所需的数据量,然后再继续。写入备用路径以处理已关闭或失败的连接。所有调用必须读取正确的数据量或

recv(Connection, &fileData[0], CHUNK_SIZE, 0);

可以提前退出离开下一个

recv(Connection, received_message, sizeof(received_message), NULL);

将图像的一部分读取为received_message,导致fileSizereceived_message没有完全填充一样疯狂。

此外,请考虑在recv上设置超时,以便在您希望终止程序时有机会读取退出标志。否则,它可能会永远阻止永远不会到达的数据。

您可以像这样轻松重用std::vector

std::vector<char> fileData;
while(isRunning)
{
ssize_t n = recv(Connection, received_message, sizeof(received_message), 0); //receiving the size of image in bytes
if (n < 0)
throw std::runtime_error(std::string("Connection error (getting fileSize)") + strerror(errno));
assert(n == sizeof(received_message));
fileSize = atoi(received_message);
if (fileSize > maxFileSize or fileSize == 0)
throw std::runtime_error("Invalid fileSize " + std::to_string(fileSize));
fileData.resize(fileSize);
size_t received = 0;
while (received < fileSize)
{
ssize_t n = recv(Connection, fileData.data() + received, fileSize - received, 0); //Receiving the image
if (n < 0)
throw std::runtime_error(std::string("Connection error (getting image)") + strerror(errno));
received += n;
}
//The code loops over and over again
}

一些注意事项:

  • 处理第一个recv未收到sizeof(received_message)字节的事件(当前受assert保护)
  • 您应该定义maxFileSize
  • 包括<cassert><exception><string>标题
  • 使用-std=c++11进行编译