C++ Filesystem Path Interator Causing Assertion Failure

I'm attempting to determine if the last element in a filesystem path is a certain value by comparing it to a string. However, at run-time, the program is failing an assertion whenever I attempt to move the iterator.

Expression: cannot dereference string iterator because the iterator was invalidated.

The cout statement functions correctly and I don't know where I'm invalidating the iterator. Ideally, I would set my iterator to parent_path().end() and then decrement it once to get the last valid element but I don't seem to be able to do this.

The MS path class doc page (https://docs.microsoft.com/en-us/cpp/standard-library/path-class?view=vs-2019#iterator) suggests that incrementing or decrementing the iterator is the correct way to iterator over the path elements, as does https://en.cppreference.com/w/cpp/experimental/fs/path.

MCVC 2019

1
2
3
4
5
6
7
8
9
10
#include <filesystem>

namespace fs = filesytem;

fs::path savePath = fs::current_path;

fs::path::iterator itr = savePath.parent_path().begin();
cout << "*itr = " + (*iter).string();

itr++;
Last edited on
Shouldn't you guard against empty paths:
1
2
fs::path::iterator itr = savePath.parent_path().begin();
if ( itr != savePath.parent_path().end() ) cout << "*itr = " + (*itr).string();
Yeah, probably, though I don't think current_path() can be empty. Even if I loop through the elements:

1
2
3
4
for (auto itr = savePath.parent_path().begin(); itr != savePath.parent_path().end(); itr++)
{
   cout << "\n*itr = " << *itr;
}

I still get the assertion failure. Surprisingly, when I try:
 
for (auto& elem : savePath.parent_path()) cout << "\n*itr = " << *elem;

I get a series of "D:"s as the output.
Last edited on
keskiverto wrote:
Shouldn't you guard against empty paths

@keskiverto, help!
It crashes to me too and I can’t see why!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <filesystem>
#include <iostream>
#include <string>


int main()
{
    auto saved_path = std::filesystem::current_path();

    std::cout << "this works:\n";
    for (const auto& e : saved_path.parent_path()) {
        std::cout << e << '\n';
    }

    std::cout << "\n- - -\nThis crashes:\n";
    for ( auto itr { saved_path.parent_path().begin() };
          itr != saved_path.parent_path().end();
          ++itr )
    {
        std::cout << "*itr = " << itr->string() << '\n';
    }
}

https://en.cppreference.com/w/cpp/filesystem/path/parent_path
path parent_path() const;
notice the return type
I guess that every time that you call `saved_path.parent_path()' you are creating another object
those iterators are not comparable

1
2
3
auto parent = saved_path.parent_path();
for( auto it = parent.begin(); it not_eq parent.end(); ++it)
   //... 



@OP: ¿is this what you want? https://en.cppreference.com/w/cpp/filesystem/path/root_directory
(look at the example)
Last edited on
ne555 wrote:
I guess that every time that you call `saved_path.parent_path()' you are creating another object

Wow! Thank you a lot, ne555! It looks so logical once you’ve clarified it :-)

And works smoothly of course:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <filesystem>
#include <iostream>
#include <string>


int main()
{
    auto saved_path = std::filesystem::current_path();
    auto parent { saved_path.parent_path() };

    for ( auto itr { parent.begin() }; itr != parent.end(); ++itr ) {
        std::cout << "*itr = " << itr->string() << '\n';
    }
}

Last edited on
hello guys! I need to make a programm that read winds in METAR messages. please help me
Last edited on
Hi @exploit, please post a new topic rather than hijacking someone else's.
@ne555

@OP: ¿is this what you want? https://en.cppreference.com/w/cpp/filesystem/path/root_directory
(look at the example)

The example isn't quite what I wanted which was to confirm the last element in the path, not the first, but I can work with this.

The fact that the iterator is a const is the answer. Many thanks.
Last edited on
It seems as if I've scoured the entire filesystem reference...twice. I saw that example, too. It helped and thanks anyway.

Since path.filename() and path.has_filename() only return or act on the last element of a path, regardless if the element represents a directory or a file, they aren't as useful as I originally thought. I've used the file_status class to better assess the nature of the last and second to last elements of a path (to help solve my problem), something like:

1
2
3
4
fs::path savePath = <some path>;
fs::file_status savepathStatus = fs::status(savePath);
if (savepathStatus.type() == fs::file_type::directory) cout << "Directory";
if (savepathStatus.type() == fs::file_type::regular) cout << "File";
Last edited on
Topic archived. No new replies allowed.