使用 boost::regex 从目录中获取带有某些正则表达式的文件名时出现意外输出

Unexpected output while getting the name of a file with some regex from a directory using boost::regex

我刚刚创建了一个函数 findFile 来查找目录 dir_name 中是否有具有某种模式 file_name_regex 的文件。只需在 Coliru

中进行测试
#include <string>
#include <iostream>
#include <boost/regex.hpp>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

bool findFile(const std::string & dir_name, const std::string & file_name_regex)
{
    fs::path p(dir_name);
    if (!exists(p))
        return false;

    boost::regex file_regex(file_name_regex, boost::regex::basic);

    fs::directory_iterator end_itr;
    for (fs::directory_iterator itr(p);itr != end_itr; ++itr )
    {   
        if (!fs::is_directory(itr->path()))
        {               
            boost::sregex_iterator it(itr->path().filename().string().begin(),
                                   itr->path().filename().string().end(), 
                                   file_regex);
            boost::sregex_iterator end;
            for (; it != end; ++it){
                std::cout << it->str() << std::endl;
            }
        }   
        else {
            continue;
        }
    }   
    return false;
}

int main()
{
    findFile("/", "a.out" );
}

使用以下命令编译并运行它:

g++ -std=c++11 -O2 -Wall -lboost_system -lboost_filesystem -lboost_regex main.cpp && ./a.out

它应该打印出来:

a.out

但它给出了意外的输出:

.out

它是基于C++ Regular Expressions with Boost Regex

的解决方案

我也在Coliru中更改了它以进行简单测试:

#include <boost/regex.hpp>
#include <iostream>
#include <string>

int main()
{
    std::string text("a.out");
    const char * pattern = "a.out";    
    boost::regex ip_regex(pattern);

    boost::sregex_iterator it(text.begin(), text.end(), ip_regex);
    boost::sregex_iterator end;
    for (; it != end; ++it) {
        std::cout << it->str() << "\n";
        // v.push_back(it->str()); or something similar     
    }
}

它打印出预期的单词 a.out

所以 我的代码有什么问题?

由于悬挂指针,您获得了 UB。临时 itr->path().filename().string() 在以下语句结束时被销毁:

        boost::sregex_iterator it(itr->path().filename().string().begin(),
                               itr->path().filename().string().end(), 
                               file_regex);

所以 begin()end() 现在指向垃圾。

您需要将临时 string 提升到一个单独的变量中以延长其生命周期:

        std::string s = itr->path().filename().string();
        boost::sregex_iterator it(s.begin(), s.end(), file_regex);