首页 > 解决方案 > 在多线程应用程序中将数组作为函数的返回值传递

问题描述

我尝试制作多线程代码,并且在某些步骤我必须检索堆上制作的数组。
这是代码:
以下函数将调用另一个名为 read_bi5_to_bin 的函数,并将传递给它的 unsigned char* 初始化为 nullptr data_bin_buffer

 int HTTPRequest::read_bi5_main(boost::filesystem::path p, ptime epoch)
{
    boost::unique_lock<boost::mutex> read_bi5_to_bin_lock(m_read_bi5_to_binMutex,boost::defer_lock);

    unsigned char *buffer;
    size_t buffer_size;

    int counter;

    size_t raw_size = 0;

    std::string filename_string = p.generic_string();
    path p2 = p;
    p2.replace_extension(".bin");
    std::string filename_string_2_bin =p2.generic_string() ;

    path p3 = p;
    p3.replace_extension(".csv");
    std::string filename_string_2_csv = p3.generic_string();

    const char *filename = filename_string.c_str();
    const char *filename_2_bin = filename_string_2_bin.c_str();

    const char *filename_2_csv = filename_string_2_csv.c_str();

    if (fs::exists(p) && fs::is_regular(p)) 
    {
        buffer_size = fs::file_size(p);
        buffer = new unsigned char[buffer_size];
    }
    else {
        //??5-17-2020 isolate multithreaded error
        read_bi5_to_bin_lock.lock();
        BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Error: couldn't access the data file. |"
            << filename << "|" << std::endl;
        read_bi5_to_bin_lock.unlock();

        return 2;
    }

    std::ifstream fin(filename, std::ifstream::binary);
    //fin.open(filename, std::ifstream::binary);
    fin.read(reinterpret_cast<char*>(buffer), buffer_size);
    fin.close();

    //5-11-2020 the next line will be commented and put in HTTPCLIent constructor
    //mHTTPRequest_Symbol_str= mHTTPRequest_HTTPClient_shared_pointer->Get_mHttpClient_HttpSymbolPrepareGet_shared_pointer()->mSymbol_strGet() ;
    std::size_t pos = mHTTPRequest_Symbol_str.find("JPY");// position of "h_ticks.bi5" in str
    double PV;
    if (pos != std::string::npos)
    {
        PV = PV_YEN_PAIR;
    }
    else
    {
        PV = PV_DOLLAR_PAIR;
    }
    //??5-17-2020 isolate multithreaded error
    read_bi5_to_bin_lock.lock();
    //5-20-2020
    //boost::shared_ptr<unsigned char> data_bin_buffer = boost::make_shared<unsigned char>() ;
    //n47::tick_data *data = n47::read_bi5_to_bin(
    //  buffer, buffer_size, epoch, PV, &raw_size, data_bin_buffer.get());
    unsigned char* data_bin_buffer = nullptr;
    n47::tick_data *data = n47::read_bi5_to_bin(
            buffer, buffer_size, epoch, PV, &raw_size, data_bin_buffer);
    //5-11-2020 here i will save binary file
    //boost::unique_lock<boost::mutex> read_bi5_to_bin_lock(m_read_bi5_to_binMutex);
    std::string file_name_path_string=output_compressed_file_2(data_bin_buffer, raw_size, filename_2_bin);
    read_bi5_to_bin_lock.unlock();

    path file_name_path_2{ file_name_path_string }; 
    buffer_size = 0;    
    if (fs::exists(file_name_path_2) && fs::is_regular(file_name_path_2)) 
    {
        //??5-17-2020 isolate multithreaded error
        read_bi5_to_bin_lock.lock();

        BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << boost::this_thread::get_id() <<"\t we can access the data .bin file. |"
            << filename_2_bin << "| with size ="<< fs::file_size(file_name_path_2) << std::endl;
        read_bi5_to_bin_lock.unlock();

    }
    else {
        //??5-17-2020 isolate multithreaded error
        read_bi5_to_bin_lock.lock();

        BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Error: couldn't access the data .bin file. |"
            << filename_2_bin << "|" << std::endl;
        read_bi5_to_bin_lock.unlock();

        return 2;
    }

    n47::tick_data_iterator iter;

    //5-11-2020 here i will save file.csv from data which is pointer to vector to pointers to ticks

    if (data == 0) {
        //??5-17-2020 isolate multithreaded error
        read_bi5_to_bin_lock.lock();

        BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Failure: Failed to load the data!" << std::endl;
        read_bi5_to_bin_lock.unlock();

        //5-14-2020 file is empty
        //return 0;
    }
    //5-15-2020 take care that without else ,error happens with empty files because data is pointer to vector of pointers to ticks .so when data is made inside read_bi5 ,it is made as null pointer and later it is assigned to vector if file has ticks.if file does not have ticks ,then it is just returned as null pointer .so when dereferencing null pointer we got error
    else if (data->size() != (raw_size / n47::ROW_SIZE)) {
        //??5-17-2020 isolate multithreaded error
        read_bi5_to_bin_lock.lock();

        BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Failure: Loaded " << data->size()
            << " ticks but file size indicates we should have loaded "
            << (raw_size / n47::ROW_SIZE) << std::endl;
        read_bi5_to_bin_lock.unlock();

        //5-14-2020 file is empty
        //return 0;
    }

    //??5-17-2020 isolate multithreaded error
    read_bi5_to_bin_lock.lock();

    BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "time, bid, bid_vol, ask, ask_vol" << std::endl;
    read_bi5_to_bin_lock.unlock();

    counter = 0;
    std::ofstream out_csv(filename_string_2_csv);
    if (data == 0)
    {

    }
    else if (data != 0)
    {
        ////read_bi5_to_bin_lock.lock();

        for (iter = data->begin(); iter != data->end(); iter++) {
            //5-11-2020 here i will save file.csv from data which is pointer to vector to pointers to ticks>>>>>>>here i should open file stream for output and save data to it
            out_csv << ((*iter)->epoch + (*iter)->td) << ", "
                << (*iter)->bid << ", " << (*iter)->bidv << ", "
                << (*iter)->ask << ", " << (*iter)->askv << std::endl;
            //??5-17-2020 isolate multithreaded error
            read_bi5_to_bin_lock.lock();

            BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) <<
                boost::this_thread::get_id() << "\t"<<((*iter)->epoch + (*iter)->td) << ", "
                << (*iter)->bid << ", " << (*iter)->bidv << ", "
                << (*iter)->ask << ", " << (*iter)->askv << std::endl;
            read_bi5_to_bin_lock.unlock();

            counter++;
        }
        ////read_bi5_to_bin_lock.unlock();

    }
    out_csv.close();
    //5-13-2020

    //??5-17-2020 isolate multithreaded error
    read_bi5_to_bin_lock.lock();

    BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << ".end." << std::endl << std::endl
        << "From " << raw_size << " bytes we read " << counter
        << " records." << std::endl
        << raw_size << " / " << n47::ROW_SIZE << " = "
        << (raw_size / n47::ROW_SIZE) << std::endl;
    read_bi5_to_bin_lock.unlock();


    delete data;
    delete[] buffer;    
    delete [] data_bin_buffer;
    return 0;
}

然后在 read_bi5_to_bin 函数中,将调用另一个函数 n47::lzma::decompress 。这是 read_bi5_to_bin 的代码:

tick_data* read_bi5_to_bin(
    unsigned char *lzma_buffer, size_t lzma_buffer_size, pt::ptime epoch,
    float point_value, size_t *bytes_read, unsigned char* buffer_decompressed) {
    tick_data *result = 0;

    // decompress
    int status;
    buffer_decompressed = n47::lzma::decompress(lzma_buffer,
        lzma_buffer_size, &status, bytes_read);

    if (status != N47_E_OK) 
    {
        bytes_read = 0;
    }
    else {
        // convert to tick data (with read_bin).
        result = read_bin(buffer_decompressed, *bytes_read, epoch, point_value);
        //delete[] buffer;
    }

    return result;
}

然后在 n47::lzma::decompress 内部,将在堆上创建一个名为 outBuffer 的数组。我需要在 data_bin_buffer 中的 read_bi5_main 检索这个缓冲区,
这是 n47::lzma::decompress 的代码

unsigned char *decompress(
        unsigned char *inBuffer, size_t inSize, int *status, size_t *outSize) {
    unsigned char *outBuffer = 0;
    elzma_file_format format = ELZMA_lzma;

    elzma_decompress_handle handle;
    handle = elzma_decompress_alloc();

    if (handle == 0) {
        *status = -1;
    } else {
        // decompression...
        datastream ds(inBuffer, inSize);
        *status = elzma_decompress_run(
            handle,
            inputCallback, static_cast<void*>(&ds),
            outputCallback, static_cast <void*>(&ds),
            format);

        if (*status == ELZMA_E_OK) {
            *outSize = ds.outData.size();
            outBuffer = new unsigned char[ ds.outData.size() ];
            std::copy(ds.outData.begin(), ds.outData.end(), outBuffer);
        }
        elzma_decompress_free(&handle);
    }

    return outBuffer;
}

当我运行它时,它给出了错误。一个非常有用的人告诉我这是问题所在,因为它只是一个字节。并建议我避免共享指针。当我将它转换为普通指针时,它会给出另一个错误如果将其初始化为 nullptr。我应该不初始化指针吗?

标签: c++arraysmultithreading

解决方案


你的read_bi5_to_bin代码坏了。

tick_data* read_bi5_to_bin(
    unsigned char *lzma_buffer, size_t lzma_buffer_size, pt::ptime epoch,
    float point_value, size_t *bytes_read, unsigned char* buffer_decompressed) {
    tick_data *result = 0;

代码接收一个名为 的指针buffer_decompressed

    // decompress
    int status;
    buffer_decompressed = n47::lzma::decompress(lzma_buffer,
        lzma_buffer_size, &status, bytes_read);

然后它丢弃它收到的值并获得其他值。

    if (status != N47_E_OK) 
    {
        bytes_read = 0;
    }
    else {
        // convert to tick data (with read_bin).
        result = read_bin(buffer_decompressed, *bytes_read, epoch, point_value);
        //delete[] buffer;
    }

    return result;
}

它永远不会返回或释放它存储在buffer_decompressed.

哎呀。


推荐阅读