问题 (std::bad_alloc) 通过 QThread 中的 QSqlQuery 将大图像(约 36 MB)保存到

Problem (std::bad_alloc) saving large image (about 36 mb) to postgres DB via QSqlQuery in QThread

本文关键字:图像 MB 保存 QThread bad std alloc 通过 中的 问题 QSqlQuery      更新时间:2023-10-16

我在尝试保存相对较大(~36 mb)的图像时遇到QSqlQuery问题。当我调用QSqlQuery::exec()时,我得到std::bad_alloc exeption。当我处理较小的图像时,一切都很好。 需要说的是 - 此代码在QThread的其他实例中执行,以防止GUI冻结,所有代码均在MinGW-32编译器中编译,PC上有8 GB RAM。有时(很少)即使使用这种大小的图像(36 mb),我也会运行此代码而没有此异常

这是代码:

......
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 MB并不多。

1) 尝试编辑您的postgresql.conf- 这可能是数据库内存限制,而不是您的应用程序。有小的默认值,大约 20Mb 的共享缓冲区。使用此链接作为示例 https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

2)要检查这是数据库还是您的问题,在exec之前,请尝试分配并释放大内存bffer - 比请求的图像大几倍。如果正常并且exec抛出内存异常,则问题出在数据库或驱动程序上,而不是您的应用程序。

3)您也可以在调试器下进入该exec,并观察bad_alloc发生在哪里