Project

General

Profile

Exiv2::ExifData.clear() crashes in Release configuration

Added by Harry McKame over 6 years ago

I'm using version 0.25 with Visual Studio 2008 and have written a simple DLL for accessing image metadata.
Everything works perfectly well when using the DebugDLL configuration.
However, when using the ReleaseDLL configuration, my DLL crashes immediately.

All I'm doing is :

static Exiv2::ExifData gexifData;
...
gexifData.clear();

If I try the functions Exiv2::XmpData:clear() and Exiv2::IptcData:clear(), they execute with no problem.
If I skip the gexifData.clear() call, I get other aborts of other kinds when using iterators, so this seems to be a general problem.

The crash is happening in the call of exifMetadata_.clear() inside the Microsoft file "c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\list" (an std file).
The line being executed is :

#if _HAS_ITERATOR_DEBUGGING
this->_Orphan_ptr(this, 0);
#endif /
_HAS_ITERATOR_DEBUGGING */

The function _Orphan_ptr() crashes because it tries to work with a pointer containing a zero.

I tried to add the following preprocessor definition :
_HAS_ITERATOR_DEBUGGING=0
to all the projects of exiv2 and to recompile everything, but that failed because of compilation errors.

For the moment I'm using the DebugDLL configuration where everything works, but I would like to use ReleaseDLL, if somebody can help.


Replies (8)

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Robin Mills over 6 years ago

Harry

I think the issue is with static. That your code runs with the debug build is good fortune. The normal use of Exiv2::ExifData is demonstrated in samples/exifprint.cpp:

Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
image->readMetadata();
Exiv2::ExifData& exifData = image->exifData();
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifData.end(); ++i) {
  ...
}
That code creates an ExifData reference on the stack from the image. The ExifData itself is something brought to life by image->readMetadata(). When you create static ExivData gexifData; it has to be initialized by program startup (or your DLL loader). Initialised to what? This is vague. What is the purpose of gexifData? The API expects you to create a reference as needed and not to have it sitting permanently in memory in an undefined state. I suspect that if you close the image (or allow it to go out of scope), any use of gexifData will also crash.

To make progress with this issue, we need to get "on the same page". Can you strip your code to the minimum required and send me the project files so I can build and reproduce your situation?

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Harry McKame over 6 years ago

Removing the static has no effect on the crash.
To answer your question: The purpose of gexifData is to accumulate meta tags for storing into future images, needing to be cleared between batches.

If I skip this initialization and try to open an image, this code immediately crashes in the for statement :

  Exiv2::XmpData &xmpData = image->xmpData();
  if (!xmpData.empty()) {
    Exiv2::XmpData::const_iterator end = xmpData.end();
    for (Exiv2::XmpData::const_iterator i = xmpData.begin(); i != end; ++i)
      func(pvar, i->key().c_str(), i->toString().c_str());
  }

It crashes in the for initialization step ("i ="), when a runtime check calls _invalid_parameter_noinfo(), which itself exists only when the _SECURE_SCL preprocessor tag is defined.
(see http://cowboyprogramming.com/2007/02/22/what-is-_invalid_parameter_noinfo-and-how-do-i-get-rid-of-it/).

Something basic is very wrong with the ReleaseDLL configuration, since both _HAS_ITERATOR_DEBUGGING and _SECURE_SCL should be off in a release build.
I don't think it has anything to do with my code, which is really quite simple.

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Robin Mills over 6 years ago

I'm going to build and run the test suite on VS2008 (our build-server builds/tests VS2005/ReleaseDLL by default). Can you confirm the version of Exiv2 you are using? (exiv2 --version --verbose).

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Harry McKame over 6 years ago

Attached are the output files for exiv2 --version --verbose for both DebugDLL and ReleaseDLL.
If you compile on VS2008 and everything works on your end, I would be very thankful if I could receive a complete copy of your project.

Suggestion: When releasing, add to the downloads a release that includes the complete compiled versions of the DLLs with object files and browse info (for all configs) etc.
That way you can be assured that the release will not be affected by special conditions on the user's computer, and also get better bug reports.

version.DebugDLL.txt (2.47 KB) version.DebugDLL.txt version info, config DebugDLL
version.ReleaseDLL.txt (2.47 KB) version.ReleaseDLL.txt version info, config ReleaseDLL

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Harry McKame over 6 years ago

Stop - this was caused by a mixup of DLLs.
There is no problem, so don't spend time on this.

However, I still stand by my above suggestion of making a complete release that does not require compilation by the user.
This way I would have avoided the error.

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Robin Mills over 6 years ago

Harry

Thanks for your suggestion about publishing the builds. Regrettably, I don't believe that is practical because of the size of the build matrix. Exiv2 supports a lot of platforms, compilers and build environments multiplied by 8 configurations (32/64bit, static/shared, release/debug). So, as this is open source we publish source and it is the user's responsibility to build the code. We provide the forum for users to request further assistance.

The Exiv2 build server arrived with v0.25 and at present you can inspect builds and test output. http://exiv2.dyndns.org:8080 The build server can build almost any configuration and a future project is to enable users to request a build from which they can collect logs and artefacts. This project is currently not resourced which means we need a volunteer. The hard work for this project is complete, however it needs more testing before it can be made available for anybody to use.

Thanks for the exiv2 --verbose --version output. You've built a vanilla v0.25 release. I've built the trunk, however it's almost the same. ReleaseDLL/Win32/VS2008 passes the test suite.

I've munged your code into exifprint.cpp and built that:

int main(int argc, char* const argv[])
try {

    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " file\n";
        return 1;
    }

    Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
    assert(image.get() != 0);
    image->readMetadata();

    Exiv2::XmpData &xmpData = image->xmpData();
    if (!xmpData.empty()) {
      Exiv2::XmpData::const_iterator end = xmpData.end();
      for (Exiv2::XmpData::const_iterator i = xmpData.begin(); i != end; ++i)
        // func(pvar, i->key().c_str(), i->toString().c_str());
        std::cout << i->key() << " -> " << i->value() << std::endl;
    }
    return 0;
}
Here's the output:
 Directory of C:\cygwin64\home\rmills\gnu\exiv2\trunk\msvc2005\bin\Win32\ReleaseDLL

08/20/2015  12:31 PM            21,504 exifprint.exe
               1 File(s)         21,504 bytes
               0 Dir(s)  11,989,237,760 bytes free

...ReleaseDLL>exifprint.exe http://dev.exiv2.org/attachments/download/805/DSC_7154.jpg
Xmp.xmp.Rating -> 0
Xmp.xmp.ModifyDate -> 2015-07-16T20:25:28+01:00
Xmp.dc.description -> lang="x-default" Classic View

C:\cygwin64\home\rmills\gnu\exiv2\trunk\msvc2005\bin\Win32\ReleaseDLL>
Here's my build-tree: (400mb zip 382,799,313 bytes): http://clanmills.com/files/ForHarry.zip

If you are unable to reproduce my success with this, a possible step forward is for us to have a 1-to-1 on Skype. I'm in England and busy this afternoon, however it's possible this evening, some of Friday and almost anytime at the weekend.

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Harry McKame over 6 years ago

My problem was only human error, but I have learned much from our discussion.
I have successfully downloaded the zip file and will take it from here.
Thanks for your outstanding support (and outstanding product).

I have recommended your product to the maintainer of the GraphicsMagick project, Bob Friesenhahn, as their metadata support is very rudimentary and they are currently thinking of rewriting themselves a similar package to yours. I think that's a pity, as it would mean a delay of several years before their package reaches maturity, while your package already exists, not mentioning the duplicated human resources.
It would be nice if two such outstanding open-source products could unify instead of compete.

For Bob, the major problem involved is your using the GPLv2 license while GraphicsMagick uses the much less-restrictive MIT/X11 license and not wishing to use any license more restrictive than LGPL. Another problem is your use of C++ while they use C, but I think that can be solved by writing an shared-library/dll as interface/bridge for C-to-C++.

I cannot speak for him or for you, just mentioning that here in passing, and the rest is up to you both.

RE: Exiv2::ExifData.clear() crashes in Release configuration - Added by Robin Mills over 6 years ago

Thanks for your compliments. The credit for the quality of Exiv2 belongs to Andreas, Gilles, Brad and Volker for writing the core code. I contribute build and user support. Writing code to read and write exif (and other meta data) is non-trivial. It doesn't make sense to do it yourself when Exiv2 provides a robust cross-platform solution which is mature, documented and tested. It doesn't make much sense for a commercial product and makes even less for an Open Source project such as GraphicsMagick. Exiv2 is used by Gimp, DigiKam and many other products.

For sure I don't see any difficulty mixing C and C++ other than name mangling which can be solved, as you've suggested, with a thin wrapper/interface.

I'm a software engineer and don't know anything about licensing. If a bridge is used, it can sniff for libexiv2 and take advantage when available. The bridge can provide simple/basic metadata support (reading Exif tags) when libexiv2 is not available. With such a strategy, I don't believe GrapicsMagick has to defer to GPLv2. If an installer is provided, libexiv2 can be optional and subject to a different user consent/agreement. However, Bob should seek legal advice.

    (1-8/8)