草庐IT

c++ - boost iostreams 断言失败

coder 2024-06-13 原文

我需要能够使用单个 fstream 以具有平台无关的文件使用方式。特别是,我需要能够在 Windows 上支持带有 unicode 字符的文件路径,同时尽可能减少对代码的侵入以支持它。因此,boost iostreams 似乎可以提供答案。然而,在尝试使用它时,我遇到了两个让我担心的失败。请参阅以下示例代码:

// MinGW (MSYS)
// GCC 4.7.2
// Boost 1.50.0
// g++ -g ifstreamtest.cpp -o test.exe -I /t/tools/boost/boost_1_50_0 -L /t/tools/boost/boost_1_50_0/stage/lib -lboost_system-mgw47-mt-d-1_50 -lboost_filesystem-mgw47-mt-d-1_50 -lboost_locale-mgw47-mt-d-1_50 -lboost_iostreams-mgw47-mt-d-1_50

#include <boost/locale.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/filesystem/path.hpp>

namespace MyNamespace
{

typedef ::boost::iostreams::file_descriptor fd;
typedef ::boost::iostreams::stream< ::boost::iostreams::file_descriptor> fstream;
typedef ::boost::iostreams::stream< ::boost::iostreams::file_descriptor_sink> ofstream;
typedef ::boost::iostreams::stream< ::boost::iostreams::file_descriptor_source> ifstream;
} // namespace MyNamespace

int main(int argc, char **argv)
{
    // Imbue boost filesystem codepoint conversions with local system
    // Do this to ensure proper UTF conversion.
    boost::filesystem::path::imbue(boost::locale::generator().generate(""));

    // Test file path.
    boost::filesystem::path file_path("test.txt");


    // Anonymous scope for temporary object.
    {
        // Open file in ctor, write to output, neglect to clean up until dtor.
        MyNamespace::ofstream output(file_path, std::ios_base::out | std::ios_base::app);
        if ( output.is_open() == false ) std::cout << "Unable to open @" << __LINE__ << std::endl;
        output << "test line 1" << std::endl;
        std::cout << "done @" << __LINE__ << std::endl;
    }
    // Temporary object destroyed while still open.

    // Anonymous scope for temporary object.
    {
        // Open file in ctor, write to output, specifically close file.
        MyNamespace::ofstream output1(file_path, std::ios_base::out | std::ios_base::app);
        if ( output1.is_open() == false ) std::cout << "Unable to open @" << __LINE__ << std::endl;
        output1 << "test line 2" << std::endl;
        output1.close();
        std::cout << "done @" << __LINE__ << std::endl;
    }
    // Temporary object destroyed.

    // Anonymous scope for temporary object.
    {
        // Default-ctor; open later. Write to file, neglect to clean up until dtor.
        MyNamespace::ofstream output2;
        // Next line causes "Assertion failed: initialized_, file t:/tools/boost/boost_1_50_0/boost/iostreams/detail/optional.hpp, line 55"
        output2->open(file_path, std::ios_base::out | std::ios_base::app);
        if ( output2.is_open() == false ) std::cout << "Unable to open @" << __LINE__ << std::endl;
        output2 << "blah test test blah" << std::endl;
    }
    // Temporary object destroyed.

//    MyNamespace::ifstream input;
// Compile success, but linker failure:
// s:\reactor\utf8stream/ifstreamtest.cpp:42: undefined reference to `void boost::iostreams::file_descriptor_source::open<boost::filesystem::path>(boost::filesystem::path const&, std::_Ios_Openmode)'
//    input->open(file_path, std::ios_base::in);

    std::cout << "done." << std::endl;
    return 0;
}

在 Windows 上,我仅限于 GCC 4.7.2 和 Boost 1.50。

评论解释了这两个失败,但我将在这里展开。对我来说,第一个也是最有问题的是当我尝试将流对象用作“普通”fstream 对象时。如果我在其构造函数中打开 fstream,那么一切都很好(如在前两个匿名范围中所见)。但是,如果我分配 fstream 对象然后尝试打开它,就会发生“坏事”。

如果我尝试调用 boost::iostreams::stream::open(),我会收到编译器错误,提示它无法将参数 1 (boost::filesystem::path) 转换为 boost::iostreams: :文件描述符接收器。当它可以用 boost::filesystem::path 构造时,为什么它不起作用?在任何一种情况下,尝试使用流的 operator->() 调用 boost::iostreams::file_descriptor_sink::open() 都会导致断言失败(如第三个匿名范围所示)。这是非常邪恶的,因为在我看来它应该抛出异常而不是使断言失败。断言失败会向我表明 boost 代码中存在错误。

我遇到的第二个失败是 typedefed fstream 和 ofstream 似乎工作正常(好吧,编译和链接)。但是当我尝试使用 ifstream 时,我在尝试调用 ifstream->open(); 时遇到链接器故障;我在 Windows(如前所述的 MinGW 配置)和 OS X 10.8.5 上使用 Apple LLVM version 4.2 (clang-425.0.28)(基于 LLVM 3.2svn) 得到了这个。因为它编译得很好而且两者之间的唯一区别是它是源还是接收器......并且两者都应该能够打开文件......这让我认为这也是 boost 中的一个错误。

有什么想法或建议吗?

最佳答案

关于编译错误:

我可以在 Linux 上使用 g++ 和 Clang++ 重现链接错误,所以这不是一个特定的 Windows 问题(我也在使用 Boost 1.55.0,所以它不是特定于 1.50)。

我想这是由头文件中允许但未在源/库中实现的模板定义引起的。

解决方案(仅针对链接问题):代替

input->open(file_path, std::ios_base::in);

使用

input->open(file_path.string(), std::ios_base::in);

这通过使用基于字符串的构造函数来规避可能错误定义的模板。

关于断言错误:

问题是您需要单独初始化 file_descriptor_sink,否则将无法正确处理 iostream 初始化。使用此代码:

//We need to initialize the sink separately
boost::iostreams::file_descriptor_sink output2Sink(file_path, std::ios_base::out | std::ios_base::app);
MyNamespace::ofstream output2(output2Sink);
if ( output2.is_open() == false ) std::cout << "Unable to open @" << __LINE__ << std::endl;
output2 << "blah test test blah" << std::endl;

open() 似乎没有重置导致断言的可选

需要对 MyNamespace::ifstream 应用相同的方法:

boost::iostreams::file_descriptor_source inputSource(file_path, std::ios_base::in);
MyNamespace::ifstream input(inputSource);
//Test reading back what we wrote earlier
std::string inputContent;
input >> inputContent;
//Prints: blah (only the first word is read!)
std::cout << "Read from test.txt: " << inputContent << std::endl;

另请注意,不必应用该解决方案来避免上述编译器错误。

通过这些修改,您的程序似乎可以在我的系统上运行。

关于c++ - boost iostreams 断言失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20849357/

有关c++ - boost iostreams 断言失败的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  5. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - 使用 rbenv 和 ruby​​-build 构建 ruby​​ 失败,出现 undefined symbol : SSLv2_method - 2

    我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby​​2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby​​-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm

  8. ruby-on-rails - Ruby 的 'open_uri' 是否在读取或失败后可靠地关闭套接字? - 2

    一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我

  9. ruby-on-rails - Ruby 流量控制 : throw an exception, 返回 nil 还是让它失败? - 2

    我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id

  10. ruby - gem 规范失败 - 2

    我正在为毕业设计开发GEM,TravisCI构建不断失败。这是我在Travis上的链接:https://travis-ci.org/ricardobond/perpetuus/builds/8709218构建错误是:$bundleexecrakerakeaborted!Don'tknowhowtobuildtask'default'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in`eval'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_

随机推荐