如何使用集合元素的向量?

时间:2022-01-21 08:21:18

So I'm streaming my Rasperry Pi camera to my computer using my program but. The vector listed below is giving me problems. It gives me std::bad_alloc after about 30 seconds of streaming. Is there any way to reuse this vector over and over again in a loop (e.g resize, clear)? Here is the simplified code:

我用我的程序把我的Rasperry Pi相机放到我的电脑上。下面列出的向量给了我一些问题。它给我std::bad_alloc,大约30秒的流。有没有办法在循环中反复使用这个向量?g大小、清楚)?这里是简化代码:

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
}

2 个解决方案

#1


2  

TCP is a streaming protocol. It has no concept of messages. Writing 10,000 bytes in at one end of the connection does not mean all 10,000 bytes will arrive at the receiver and be available all at once.

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

As a result, recv works with what is has. It returns whatever is currently available, and if nothing is available recv waits until data becomes available. This means if you ask for 10,000 bytes you may get anywhere between 1 byte and 10,000 bytes entirely at the whim of the network stack, the maximum amount of data that can go in one IP packet, and too many other variables to list.

因此,recv与is一起工作。它返回当前可用的任何内容,如果没有可用的recv,则等待数据变为可用。这意味着,如果您请求10,000字节,您可能会完全在网络堆栈的突发奇想中得到1字节到10,000字节之间的任何位置,一个IP包中可以传输的最大数据量,以及太多其他要列出的变量。

So

所以

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

may return before it receives all of received_message. fileSize will computed from bad input, most likely a string that isn't null terminated and runs off the end of the buffer triggering undefined behaviour, and garbage in gives garbage out.

可能在它接收到所有的received_message之前返回。fileSize将从错误的输入中进行计算,最可能的是一个不是null终止的字符串,并运行到缓冲区的末端,从而触发未定义的行为,而garbage in将输出垃圾。

This incorrect fileSize is then used to size a vector which will now almost certainly be the wrong size. If it is too small,

这个不正确的fileSize然后被用于确定向量的大小,现在几乎可以肯定这个向量的大小是错误的。如果太小,

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

may run off the end of the vectorfor more undefined behaviour. If it is too large, the system may not be able to allocate storage for the vector because there isn't enough contiguous storage available. This appears to be what has happened to OP.

可能会在矢量末端运行,以获得更多未定义的行为。如果它太大,系统可能无法为向量分配存储,因为没有足够的连续存储可用。这似乎是OP所发生的事情。

Solution: Loop all calls to recv until the required amount of data has arrived before proceeding. Write in an alternate path to handle closed or failed connections. All calls must read the correct amount of data or

解决方案:将所有调用循环到recv,直到所需的数据量到达后才继续。编写一个备用路径来处理关闭或失败的连接。所有调用都必须读取正确的数据量

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

could exit early leaving the next

能早点离开下一个吗

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

to read part of the image as received_message, resulting in a fileSize every bit as insane as if received_message was not completely filled.

将图像的一部分作为received_message进行读取,从而导致对每个位进行分割,就像received_message没有完全填充一样。

Also Consider setting a timeout on recv so that you have a chance to read an exit flag should you wish to terminate the program. Otherwise it may block forever for data that will never arrive.

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

#2


0  

You can easily reuse your std::vector like this:

您可以很容易地重用std::矢量如下:

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
}

A few notes:

一些笔记:

  • Handle the event that the first recv does not receive sizeof(received_message) bytes (currently protected by the assert)
  • 处理第一个recv没有接收sizeof(received_message)字节(当前受assert保护)的事件
  • You should define maxFileSize
  • 你应该定义maxFileSize
  • Include the <cassert>, <exception> and <string> headers
  • 包括 header .
  • Compile using -std=c++11
  • 编译使用化= c++ 11

#1


2  

TCP is a streaming protocol. It has no concept of messages. Writing 10,000 bytes in at one end of the connection does not mean all 10,000 bytes will arrive at the receiver and be available all at once.

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

As a result, recv works with what is has. It returns whatever is currently available, and if nothing is available recv waits until data becomes available. This means if you ask for 10,000 bytes you may get anywhere between 1 byte and 10,000 bytes entirely at the whim of the network stack, the maximum amount of data that can go in one IP packet, and too many other variables to list.

因此,recv与is一起工作。它返回当前可用的任何内容,如果没有可用的recv,则等待数据变为可用。这意味着,如果您请求10,000字节,您可能会完全在网络堆栈的突发奇想中得到1字节到10,000字节之间的任何位置,一个IP包中可以传输的最大数据量,以及太多其他要列出的变量。

So

所以

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

may return before it receives all of received_message. fileSize will computed from bad input, most likely a string that isn't null terminated and runs off the end of the buffer triggering undefined behaviour, and garbage in gives garbage out.

可能在它接收到所有的received_message之前返回。fileSize将从错误的输入中进行计算,最可能的是一个不是null终止的字符串,并运行到缓冲区的末端,从而触发未定义的行为,而garbage in将输出垃圾。

This incorrect fileSize is then used to size a vector which will now almost certainly be the wrong size. If it is too small,

这个不正确的fileSize然后被用于确定向量的大小,现在几乎可以肯定这个向量的大小是错误的。如果太小,

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

may run off the end of the vectorfor more undefined behaviour. If it is too large, the system may not be able to allocate storage for the vector because there isn't enough contiguous storage available. This appears to be what has happened to OP.

可能会在矢量末端运行,以获得更多未定义的行为。如果它太大,系统可能无法为向量分配存储,因为没有足够的连续存储可用。这似乎是OP所发生的事情。

Solution: Loop all calls to recv until the required amount of data has arrived before proceeding. Write in an alternate path to handle closed or failed connections. All calls must read the correct amount of data or

解决方案:将所有调用循环到recv,直到所需的数据量到达后才继续。编写一个备用路径来处理关闭或失败的连接。所有调用都必须读取正确的数据量

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

could exit early leaving the next

能早点离开下一个吗

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

to read part of the image as received_message, resulting in a fileSize every bit as insane as if received_message was not completely filled.

将图像的一部分作为received_message进行读取,从而导致对每个位进行分割,就像received_message没有完全填充一样。

Also Consider setting a timeout on recv so that you have a chance to read an exit flag should you wish to terminate the program. Otherwise it may block forever for data that will never arrive.

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

#2


0  

You can easily reuse your std::vector like this:

您可以很容易地重用std::矢量如下:

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
}

A few notes:

一些笔记:

  • Handle the event that the first recv does not receive sizeof(received_message) bytes (currently protected by the assert)
  • 处理第一个recv没有接收sizeof(received_message)字节(当前受assert保护)的事件
  • You should define maxFileSize
  • 你应该定义maxFileSize
  • Include the <cassert>, <exception> and <string> headers
  • 包括 header .
  • Compile using -std=c++11
  • 编译使用化= c++ 11