2017-01-20 25 views
2

因此,我使用我的程序將我的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 
} 
+1

這段代碼沒有意義。你不能傳遞一個指向recv函數的向量。它應該比30多歲後快速崩潰。 –

+2

@MK,OP傳遞一個指向矢量元素的指針(所以,一個'char *'),而不是整個矢量。 – SingerOfTheFall

+1

也注意到沒有什麼可以阻止'recv(Connection,received_message,sizeof(received_message),NULL);'只返回'received_message'的一部分,導致完全搞砸了'fileSize'。 – user4581301

回答

2

TCP是流協議,包括了<cassert><exception><string>

  • 編譯。它沒有消息的概念。在連接的一端寫入10,000個字節並不意味着所有的10,000個字節都將到達接收器並且一次全部可用。

    因此,recv與已有的一起工作。它返回當前可用的任何數據,如果沒有可用的數據,recv將等待數據變爲可用。這意味着,如果要求輸入10,000個字節,則可能會在網絡堆棧的意外事件中獲得1個字節到10,000個字節之間的任何位置,可以在一個IP數據包中傳輸的最大數據量以及要列出的其他變量。

    所以它接收所有的received_message

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

    可能返回。 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,每位導致fileSize的瘋狂彷彿received_message沒有完全填滿。

    另請考慮在recv上設置超時時間,以便您有機會在您希望終止程序時讀取退出標誌。否則,它可能會永遠阻止永遠不會到達的數據。

  • 0

    您可以輕鬆地重用你的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
    • 使用-std=c++11
    +0

    斷言完全正常的狀態,'recv'不返回請求的數據量,這是一個非常非常糟糕的主意。 – user4581301

    +0

    @ user4581301是的,這是OP的一個練習(雖然有一個例子) – Jonas

    相關問題