Bertwim van Beest
Bertwim van Beest

Reputation: 1811

std::filesystem::copy throws std::__ios_failure: what to do?

The c++ program I'm working on invariably crashes when a certain directory is copied (using std::filesystem::copy) to a new location. The error message I get is:

terminate called after throwing an instance of 'std::__ios_failure'
  what():  basic_filebuf::underflow error reading the file: Input/output error
Abort (core dumped)

I found the underlying problem when I tried to copy the very directory by hand. In this directory, containing jpg-images, there was one file apparently corrupt: If, from the command line I type (linux)

cp 20220810-15174296.jpg corrupt.jpg
cp: error reading '20220810-15174296.jpg': Input/output error

Apparently, something is wrong with the image 20220810-15174296.jpg, although it looks normal and can be displayed. My question is not about this corrupt file, but how can I prevent my program from crashing. It seems that the offending exception std::__ios_failure cannot be caught. A minimal program that is already showing the issue is

#include <exception>
#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main( int argc, char* argv[] )
{
   try
   {
      fs::path src( "/path/to/src" );
      fs::path trg( "/path/to/trg" );
      fs::copy( src, trg, fs::copy_options::recursive );
   }
   catch ( ... )
   {
      std::cout << "ERROR occurred" << std::endl;
   }
   return 0;
}

No matter how I do the catch (std::system_error, fs::filesystem_error, std::exception, ...), the std::__ios_failure terminates the program as indicated. Also using the fs::copy overloads with the std::error_code argument does not change the situation.

The above program is compiled with either g++ (13.2.1) or clang++ (18.0.0), but the result is the same:

g++ -O3 --std=c++20 fscopy.cpp && ./a.out
terminate called after throwing an instance of 'std::__ios_failure'
  what():  basic_filebuf::underflow error reading the file: Input/output error
Abort (core dumped)

and

clang++ -O3 --std=c++20 fscopy.cpp && ./a.out
terminate called after throwing an instance of 'std::__ios_failure'
  what():  basic_filebuf::underflow error reading the file: Input/output error
Abort (core dumped)

Upvotes: 3

Views: 380

Answers (1)

Bertwim van Beest
Bertwim van Beest

Reputation: 1811

All thanks for the comments made. Let me summarise my findings

  1. The root cause of the problem seems to be a luring hardware issue.
  2. The standard c++ techniques, using std::filesystem with both overloads of fs::copy (std::system_error or exception throwing) all fail, as these functions throw an std::__ios_failure exception that cannot be caught. (both g++ and clang++).
  3. The latter remark seems to me a bug in the implementation of 'std::filesystem::copy' in the standard <filesystem> as used by the mentioned compilers.
  4. Boost::filesystem::copy is robust against the particular failure I experienced. If I favour robustness over using the standard, this is the way to go.

Upvotes: 0

Related Questions