У меня проблема с QSqlQuery при попытке сохранить относительно большое (~ 36 МБ) изображение. Когда я вызываю QSqlQuery::exec(), я получаю исключение std::bad_alloc. Когда я работаю с меньшими изображениями, все в порядке. Нужно сказать - этот код выполняется в другом экземпляре QThread, чтобы предотвратить зависание графического интерфейса, весь код скомпилирован в компиляторе MinGW-32, на ПК 8 ГБ ОЗУ. И иногда (очень редко) у меня этот код работает без этого исключения даже с изображениями такого размера (36 МБ)
вот код:
......
QByteArray byte_array_image, byte_array_icon;
QBuffer buffer_image(&byte_array_image), buffer_icon(&byte_array_icon);
buffer_image.open(QIODevice::WriteOnly);
buffer_icon.open(QIODevice::WriteOnly);
image->save(&buffer_image, format.toLocal8Bit().data());
icon->save(&buffer_icon, "JPEG");
query.prepare("INSERT INTO pictures (id, id_act, date_time, name, picture, icon) VALUES (:id, :id_act, :date_time, :name, :picture, :icon)");
......
query.bindValue(":picture", byte_array_image);
query.bindValue(":icon", byte_array_icon);
byte_array_image.clear();
byte_array_icon.clear();
save_succeed = query.exec();
if (!save_succeed)
emit database_failed(QUERY_ERROR_HEADER, QUERY_ERROR_SAVE_IMAGE + query.lastError().text());
emit query_finished();
return save_succeed;
Насколько я вижу, проблема может быть связана с нехваткой места в куче для QApplication для создания экземпляра QString, включающего весь байт-код изображения. Чтобы исправить это, я попытался разбить это изображение на десять частей, но это не помогает.
Вот код запроса, разделенный на десять частей:
............
QByteArray byte_array_image, byte_array_icon;
QBuffer buffer_image(&byte_array_image), buffer_icon(&byte_array_icon);
buffer_image.open(QIODevice::WriteOnly);
buffer_icon.open(QIODevice::WriteOnly);
image->save(&buffer_image, format.toLocal8Bit().data());
icon->save(&buffer_icon, "JPEG");
int partlen, parts_count = 0;
save_succeed = false;
while (!save_succeed && ++parts_count < 10)
{
partlen = byte_array_image.size();
partlen = byte_array_image.size() / parts_count;
query.clear();
query.prepare("INSERT INTO pictures (id, id_act, date_time, name, part_one, parts_count, icon, src, src_act) "
"VALUES (:id, :id_act, :date_time, :name, :part_one, :parts_count, :icon, :src, :src_act)");
........
query.bindValue(":part_one", byte_array_image.mid(0, partlen));
query.bindValue(":parts_count", parts_count);
query.bindValue(":icon", byte_array_icon);
try
{
save_succeed = query.exec();
}
catch (std::bad_alloc &error)
{
if (parts_count < 10)
continue;
emit database_failed(QUERY_HEAP_ERROR_HEADER, QUERY_HEAP_ERROR_TEXT);
return false;
}
}
if (save_succeed)
{
QStringList part_names = { "part_one", "part_two", "part_three", "part_four", "part_five",
"part_six", "part_seven", "part_eight", "part_nine", "part_ten"};
for (int current_part = 1; current_part < parts_count; ++current_part)
{
query.clear();
query.prepare("UPDATE pictures SET "+part_names[current_part]+" = :current_part WHERE id = :id AND src = :src");
query.bindValue(":current_part", current_part == parts_count - 1 ? byte_array_image.mid(current_part*partlen) : byte_array_image.mid(current_part*partlen, partlen));
........
save_succeed = query.exec();
}
}
byte_array_image.clear();
byte_array_icon.clear();
Я прав с источником проблемы? Могу ли я что-нибудь сделать, чтобы это исправить? 36 мб для изображения не так уж и много.
query.exec()
делает внутри. Ты? Если нет, то вы не можете контролировать то, что выделяется. Во-вторых,std::bad_alloc
также выбрасывается, когда для выделения дается недопустимое (то есть отрицательное) число. Кроме того, вместо 10 частей, как насчет 100 частей? Или 1000 деталей? Выясните, действительно ли это связано с памятью или это просто ошибка в вашем коде. - person PaulMcKenzie   schedule 23.08.2019