commit 65025629c248fe1adbef4956bba7a420ca4fa30b
parent 75ab892435b3b559596b0b900aac46230dc884df
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 14 Sep 2005 21:54:18 +0000
N. Durner wrote:
Hi Christian,
zumindest unter Windows bringt der exiv2 Extractor den Aufrufer bei größeren
Dateien (hier 800 MB) zum Absturz.
Verursacht wird das Problem durch vector::reserve() in MemIo::MemIo() (basicio.
cpp).
Ich habe die Speicherverwendung so geändert, dass der Speicherblock für die zu
extrahierende Datei nicht mehr für den exiv2 Extractor dupliziert werden muss.
Was meinst Du dazu (s. Anhang)?
Stefan: als Workaround kann libextractor_exiv2.dll einfach umbenannt werden, so dass das Modul nicht mehr geladen wird.
Grüße,
Nils
Diffstat:
4 files changed, 59 insertions(+), 20 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,7 @@
+Wed Sep 14 15:02:49 PDT 2005
+ Avoid malloc/memcpy of file in exiv2 extractor (optimization, avoids
+ problems with very large files where malloc may run into problems).
+
Wed Sep 14 13:50:15 PDT 2005
Changed code for backwards-compatibility with zlib 1.1
(thanks to Ronan Melennec).
diff --git a/src/plugins/exiv2/basicio.cpp b/src/plugins/exiv2/basicio.cpp
@@ -339,10 +339,27 @@ namespace Exiv2 {
{
// If copying data is too slow it might be worth
// creating a readonly MemIo variant
- data_.reserve(size);
- data_.assign(data, data+size);
- idx_ = 0;
+ idx_ = 0;
+ data_ = (byte *) malloc(size);
+ if (data_)
+ {
+ memcpy(data_, data, size);
+ size_ = size;
+ isMalloced = true;
+ }
+ else
+ {
+ size = 0;
+ isMalloced = false;
+ }
}
+
+ void MemIo::wrap(const byte *data, long size)
+ {
+ data_ = (byte *) data;
+ size_ = size;
+ isMalloced = false;
+ }
BasicIo::AutoPtr MemIo::temporary() const
{
@@ -352,15 +369,17 @@ namespace Exiv2 {
void MemIo::checkSize(long wcount)
{
ByteVector::size_type need = wcount + idx_;
- if (need > data_.size()) {
- data_.resize(need);
+ if (need > size_) {
+ if (size_ > 0)
+ data_ = (byte *) realloc(data_, need);
+ else
+ data_ = (byte *) malloc(need);
}
}
long MemIo::write(const byte* data, long wcount)
{
checkSize(wcount);
- // According to Josuttis 6.2.3 this is safe
memcpy(&data_[idx_], data, wcount);
idx_ += wcount;
return wcount;
@@ -371,12 +390,20 @@ namespace Exiv2 {
MemIo *memIo = dynamic_cast<MemIo*>(&src);
if (memIo) {
// Optimization if this is another instance of MemIo
- data_.swap(memIo->data_);
+ if (memIo->isMalloced)
+ {
+ isMalloced = true;
+ memIo->isMalloced = false;
+ }
+ else
+ isMalloced = false;
+
+ data_ = memIo->data_;
idx_ = 0;
}
else{
// Generic reopen to reset position to start
- data_.clear();
+ free(data_);
idx_ = 0;
if (src.open() != 0) {
throw Error(9, src.path(), strError());
@@ -422,10 +449,10 @@ namespace Exiv2 {
}
else {
assert(pos == BasicIo::end);
- newIdx = data_.size() + offset;
+ newIdx = size_ + offset;
}
- if (newIdx < 0 || newIdx > data_.size()) return 1;
+ if (newIdx < 0 || newIdx > size_) return 1;
idx_ = newIdx;
return 0;
}
@@ -437,7 +464,7 @@ namespace Exiv2 {
long MemIo::size() const
{
- return (long)data_.size();
+ return (long) size_;
}
int MemIo::open()
@@ -466,10 +493,9 @@ namespace Exiv2 {
long MemIo::read(byte* buf, long rcount)
{
- long avail = (long)(data_.size() - idx_);
+ long avail = (long)(size_ - idx_);
long allow = std::min(rcount, avail);
- // According to Josuttis 6.2.3 this is safe
memcpy(buf, &data_[idx_], allow);
idx_ += allow;
return allow;
@@ -477,7 +503,7 @@ namespace Exiv2 {
int MemIo::getb()
{
- if (idx_ == data_.size())
+ if (idx_ == size_)
return EOF;
return data_[idx_++];
}
@@ -489,7 +515,7 @@ namespace Exiv2 {
bool MemIo::eof() const
{
- return idx_ == data_.size();
+ return idx_ == size_;
}
std::string MemIo::path() const
diff --git a/src/plugins/exiv2/basicio.hpp b/src/plugins/exiv2/basicio.hpp
@@ -476,7 +476,7 @@ namespace Exiv2 {
//! @name Creators
//@{
//! Default constructor that results in an empty object
- MemIo() { idx_ = 0; }
+ MemIo() { idx_ = 0; isMalloced = false; data_ = NULL;}
/*!
@brief Constructor that accepts a block of memory to be copied.
IO operations are performed on the copied memory.
@@ -486,7 +486,10 @@ namespace Exiv2 {
*/
MemIo(const byte* data, long size);
//! Destructor. Releases all managed memory
- virtual ~MemIo() {}
+ ~MemIo() {if (isMalloced) free(data_);}
+
+ void MemIo::wrap(const byte *data, long size);
+
//@}
//! @name Manipulators
@@ -631,8 +634,11 @@ namespace Exiv2 {
typedef std::vector<byte> ByteVector;
// DATA
- ByteVector data_;
- ByteVector::size_type idx_;
+ byte *data_;
+ ByteVector::size_type idx_, size_;
+
+ // Was the buffer allocated?
+ bool isMalloced;
// METHODS
void checkSize(long wcount);
diff --git a/src/plugins/exiv2/image.cpp b/src/plugins/exiv2/image.cpp
@@ -142,7 +142,10 @@ namespace Exiv2 {
Image::AutoPtr ImageFactory::open(const byte* data, long size)
{
- BasicIo::AutoPtr io(new MemIo(data, size));
+ MemIo *mem = new MemIo();
+ mem->wrap(data, size);
+
+ BasicIo::AutoPtr io(mem);
Image::AutoPtr image = open(io); // may throw
if (image.get() == 0) throw Error(12);
return image;