c++occi

Access Violation with OCCI next() and setDataBuffer()


unfortunately I can't see the forest for the trees and need help. I call a result set via a SELECT statement, which has 70 columns. I initialize my buffer for all 70 columns which are chars and set them with setDataBuffer. Unfortunately I can only retrieve 15-17 records. After that I get an Access Violation error message. If I try next(1000) it does not work at all. I think it has something to do with the pointers but I don't see the error. Does anyone know what I am doing wrong?

            #pragma region Arrays
            char*** data_array  = new char**[70];
            for (unsigned int i = 0; i < 70; ++i)
            {
                data_array[i] = new char*[1000];
                for (unsigned int j = 0; j < 1000; ++j)
                {
                    data_array[i][j] = new char[500];
                }
            }

            ub2**   size_array  = new ub2 * [70];
            for (unsigned int i = 0; i < 70; ++i)
            {
                size_array[i] = new ub2[1000];
            }

            sb2**   ind_array   = new sb2 * [70];
            for (unsigned int i = 0; i < 70; ++i)
            {
                ind_array[i] = new sb2[1000];
            }

            ub2**   rc_array    = new ub2 * [70];
            for (unsigned int i = 0; i < 70; ++i)
            {
                rc_array[i] = new ub2[1000];
            }
            #pragma endregion

            #pragma region setDataBuffer
            for (unsigned int i = 0; i < 70; ++i)
            {
                resultSet->setDataBuffer(i + 1, data_array[i][0], OCCI_SQLT_STR, 500, size_array[i], ind_array[i], rc_array[i]);
            }
            #pragma endregion

            try
            {
                ResultSet::Status resultSetStatus = resultSet->next(25);
                if (resultSetStatus == ResultSet::Status::DATA_AVAILABLE)
                {
                    unsigned int rowCount = resultSet->getNumArrayRows();
                    for (unsigned int row = 0; row < rowCount; ++row)
                    {
                        for (unsigned int column = 0; column < 70; ++column)
                        {
                            auto value =  data_array[column][row];
                            auto vsize = *size_array[column];

                            std::string cellContent(value, vsize);
                        }
                    }
                }
            }
            catch(SQLException& sqlEx)
            {
                std::string msg = sqlEx.getMessage();
                int i = 0;
            }

Solution

  • The problem is your allocation of data_array, because you create it as a jagged array, not a contiguous array of memory as needed by setDataBuffer.

    If you want do use dynamic allocation using new[] I suggest something like this instead:

    using data_type = int8_t[1000][500];
    auto data_array = new data_type[70];
    

    Then each element of data_array will be a contiguous area of memory, 1000 * 500 bytes large.


    If you want to know the difference between an array of arrays (as in my solution) and your pointer to pointer (jagged array), see e.g. this old answer of mine.