openvdb icon indicating copy to clipboard operation
openvdb copied to clipboard

[BUG] Save multiple times using the same file or std::ostream with io::Stream

Open lucapagani opened this issue 3 years ago • 2 comments

Environment

Operating System: Linux Version / Commit SHA: OpenVDB 8.0 Other: compiler clang

Describe the bug

If we try to use the same std::ostream (or file) multiple times there is a segmentation fault due to bad data returned by pword.

To Reproduce

Steps to reproduce the behavior:

  1. Build with OpenVDB with clang
  2. Build the example below
  3. Run the executable

Example:

#include <openvdb/io/Stream.h>
#include <openvdb/openvdb.h>
#include <openvdb/tools/LevelSetSphere.h>

#include <fstream>
#include <iostream>

int main ( int argc, char const *argv[] ) {
  openvdb::initialize ();

  // Create sphere
  float radius = 5.0f;
  openvdb::Vec3f center ( 1.0, 0.5, 0.3 );
  float voxelSize = 0.3f;

  std::vector<openvdb::FloatGrid::Ptr> spheres;

  for ( size_t i = 0; i < 3; ++i )
    spheres.push_back ( openvdb::tools::createLevelSetSphere<openvdb::FloatGrid> ( radius + 0.5 * i, center, voxelSize ) );

  // Save grid to file
  std::ofstream outFile ( "test.vdb", std::ios_base::binary );

  for ( size_t i = 0; i < 1; ++i ) {
    openvdb::GridPtrVecPtr grids ( new openvdb::GridPtrVec );
    grids->push_back ( spheres[ i ] );

    openvdb::io::Stream stream ( outFile );
    stream.setCompression ( openvdb::io::COMPRESS_NONE );
    stream.write ( *grids );
  }

  return 0;
}

Expected behavior

Each vector of grids is written to the same ostream.

Additional context

Adding io::clearStreamMetadataPtr(os); at the end of void Archive::write(std::ostream& os, const GridCPtrVec& grids, bool seekable, const MetaMap& metadata) const in Archive.cc fixed the issue for me.

lucapagani avatar Jul 26 '21 06:07 lucapagani

Hi @lucapagani - sorry for the delayed response. I think I remember looking into this a while back and coming to the conclusion that, unfortunately, a openvdb::io::Stream is not designed to be used this way. The write methods on the stream/archive/file classes are designed to write an entire file, start to end, not to be able to append to an existing filestream in the way you're using it. I'm suprised this actually works after your change, I would have expected the contents of the stream to be overwritten by the last call?

We should at the very least try to turn this fault into an exception (your fix may even be more correct as it mutates the underlying static stream obj) and improve the documentation if the above is correct.

Idclip avatar May 16 '22 20:05 Idclip

Hi @Idclip, thanks for the answer. Without any changes, it actually worked as expected sometimes on Windows, while it has always failed on Linux. It worked after that fix: the grids where correctly appended in the file, and there wasn't any problem in reading them. But I've tested few cases with a custom type, float and mask. In the end, we were able to append multiple grids in our file converting the grid to a std stream.

lucapagani avatar May 21 '22 15:05 lucapagani