![](/img/trans.png)
[英]Why does boost::filesystem::path return a path instead of string
[英]Why is boost::filesystem aborting instead of throwing an exception?
我正在將一些代碼從VS2010(使用Boost 1.55)遷移到VS 2015(使用Boost 1.60)。
我最終得到“ Microsoft Visual C ++運行時庫”的報告,報告在boost引發異常時abort() has been called
了abort() has been called
。 但是,我可以毫無問題地拋出其他異常(並且它過去曾與VS2010 / boost1.55一起使用):
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <iostream>
int main( int argc, char* argv[] )
{
// Stepping to folder:
try
{
boost::filesystem::current_path("B:/dev/msvc2015/vobs_bci/public/tst/base/cppunit/utlfile");
std::cout << "Worked" << std::endl; // works OK
}
catch (...)
{
}
// test throwing upon copy_directory because dource folder does not exist:
try
{
boost::filesystem::copy_directory("s", "b");
}
catch (...)
{
std::cout << "Caught" << std::endl; // works OK
}
// test throwing upon copy because target file already exists:
try
{
boost::filesystem::copy("./test.h", "./copied.cpp"); // works
boost::filesystem::copy("./test.h", "./copied.cpp"); // should throw and be caught
}
catch (...)
{
std::cout << "Caught" << std::endl; // never reached...
}
std::cout << "Done" << std::endl;
return 0;
}
輸出:
Worked
Caught
-> then aborts!
使用調試器,我看到當下面的錯誤函數(在filesystem / src / operations.cpp中)調用BOOST_FILESYSTEM_THROW
調用了BOOST_FILESYSTEM_THROW
:
bool error(err_t error_num, const path& p1, const path& p2, error_code* ec,
const char* message)
{
if (!error_num)
{
if (ec != 0) ec->clear();
}
else
{ // error
if (ec == 0)
BOOST_FILESYSTEM_THROW(filesystem_error(message,
p1, p2, error_code(error_num, system_category()))); // << Here!
else
ec->assign(error_num, system_category());
}
return error_num != 0;
}
我檢查了調試器,然后到達了filesystem_error
構造函數,可以毫無問題地退出該程序,下一步(在調試器中按F11鍵,現在應調用throw
),然后調用abort()
。
奇怪的是,當copy_directory
引發異常時,它也起作用,並且確實在filesystem/src/operations.cpp
中調用了完全相同的error
函數 。
中止時的調用堆棧為:
> ntdll.dll!KiUserExceptionDispatcher() Inconnu
KernelBase.dll!RaiseException() Inconnu
vcruntime140d.dll!_CxxThrowException(void * pExceptionObject=0x000000000019f670, const _s__ThrowInfo * pThrowInfo=0x000000013fd01870) Ligne 136 C++
test_3rdparty_inprg_boost.exe!`anonymous namespace'::error(unsigned long error_num=80, const boost::filesystem::path & p1={...}, const boost::filesystem::path & p2={...}, boost::system::error_code * ec=0x0000000000000000, const char * message=0x000000013fcf6fb8) Ligne 321 C++
test_3rdparty_inprg_boost.exe!boost::filesystem::detail::copy_file(const boost::filesystem::path & from={...}, const boost::filesystem::path & to={...}, boost::filesystem::detail::copy_option option=none, boost::system::error_code * ec=0x0000000000000000) Ligne 919 C++
test_3rdparty_inprg_boost.exe!boost::filesystem::copy_file(const boost::filesystem::path & from={...}, const boost::filesystem::path & to={...}, boost::filesystem::copy_option option=none, boost::system::error_code & ec) Ligne 550 C++
test_3rdparty_inprg_boost.exe!boost::filesystem::detail::copy(const boost::filesystem::path & from={...}, const boost::filesystem::path & to={...}, boost::system::error_code * ec=0x0000000000000000) Ligne 894 C++
test_3rdparty_inprg_boost.exe!boost::filesystem::copy(const boost::filesystem::path & from={...}, const boost::filesystem::path & to={...}) Ligne 524 C++
test_3rdparty_inprg_boost.exe!main(int argc=1, char * * argv=0x00000000003f3cc0) Ligne 35 C++
test_3rdparty_inprg_boost.exe!invoke_main() Ligne 75 C++
但是我看不到ntdll.dll!KiUserExceptionDispatcher()
或KernelBase.dll!RaiseException()
的源代碼。
boost::filesystem::copy
是一個巨大的混亂局面。 該函數只調用boost::filesystem::detail::copy
,第三個參數默認為null:
BOOST_FILESYSTEM_DECL
void copy(const path& from, const path& to, system::error_code* ec)
{
file_status s(symlink_status(from, *ec));
if (ec != 0 && *ec) return;
if(is_symlink(s))
{
copy_symlink(from, to, *ec);
}
else if(is_directory(s))
{
copy_directory(from, to, *ec);
}
else if(is_regular_file(s))
{
copy_file(from, to, fs::copy_option::fail_if_exists, *ec);
}
else
{
if (ec == 0)
BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy",
from, to, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category())));
ec->assign(BOOST_ERROR_NOT_SUPPORTED, system_category());
}
}
該函數反過來充滿了對該潛在為null的指針的無效取消引用,並且還調用了聲明為noexcept的特定函數的錯誤代碼變體,傳遞了由於取消引用了null指針而導致的虛假引用,編譯器可能會轉發因此(請記住,我們已經在UB國土上了)。 這些函數依次獲取引用的地址(通常再次產生空指針),並再次調用其自身的詳細信息版本,后者使用錯誤函數,如果錯誤代碼指針為null,則拋出該錯誤。
解決方法:
copy()
,如果您想要的東西使用具體的函數(例如, copy_file()
),或者 error_code
的copy()
版本並親自檢查代碼。 我看到您已經發布了一個錯誤報告。 此錯誤報告是正確的。
通過jpo38編輯:
不要使用
copy()
請注意,在最新版本的boost 1.65.1中仍然如此。 您可以通過將功能標記為已棄用來阻止開發人員使用該功能:
創建一個包含以下內容的文件:
#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif
...
namespace boost
{
namespace filesystem
{
class path;
DEPRECATED( void copy(const path& from, const path& to) );
}
}
然后使用/FI
選項將其包括在所有cpp文件中。 然后,如果有任何代碼嘗試使用此凌亂的函數,則會收到警告。
參見boost源代碼 。 據此, BOOST_FILESYSTEM_THROW(EX)
只是throw EX
。 因此,一定有一個原因,為什么拋出調用abort()
。 當拋出異常而又拋出另一個異常時(例如在異常構造函數中),情況可能就是這樣。
目前,我的假設是boost::filesystem
的錯誤。 您可能考慮提交錯誤報告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.