序列化 filesystem::path 对象时的未定义行为

Undefined Behavior When Serializing filesystem::path Object

我有以下代码在测试 filesystem::path 对象的序列化和反序列化时工作得很好:

#include <filesystem>
#include <array>
#include <iostream>

int main() {
    namespace fs = std::filesystem;
    std::array<char, sizeof(fs::path)> arr;
    fs::path currentPath("./Icon");
    memcpy(&arr[0], &currentPath, sizeof(fs::path));
    currentPath = fs::path("./Characters");         //Change currentPath before performing memcpy deserializing for testing purposes
    memcpy(&currentPath, &arr[0], sizeof(fs::path));
    std::cout << currentPath.filename();
}

这很完美,序列化为字节数组并按预期反序列化。直到我使用不同的文件路径,例如将初始路径与以下测试路径交换:

#include <filesystem>
#include <array>
#include <iostream>

int main() {
    namespace fs = std::filesystem;
    std::array<char, sizeof(fs::path)> arr;
    fs::path currentPath("./Characters");
    memcpy(&arr[0], &currentPath, sizeof(fs::path));
    currentPath = fs::path("./Icon");                   //Change currentPath before performing memcpy deserializing for testing purposes
    memcpy(&currentPath, &arr[0], sizeof(fs::path));
    std::cout << currentPath.filename();
}

当我 运行 这个版本的代码时,currentPath 对象最终被破坏。

两个不同但真实的目录的不同行为使我相信未定义的行为已经在某处滑落,但我不确定确切的位置。同样,文件路径中使用的目录是真实的,但即使它们不是真实的,我也不明白为什么它会影响路径对象的序列化和反序列化,因为路径对象可用于表示不存在的文件路径。

这个答案是针对 libcxx std::filesystem (Clang) 但我假设其他 STL 实现具有相同的:

这意味着当您执行 currentPath = fs::path("./Icon"); 时,现有字符串将被 std::string's operator= and the pointer you stashed becomes invalid. That it contains any recognizable value at all is up to many factors, including potentially the small string optimization, other threads' activity 和运气释放。

如果你运行这段代码在 Clang 的 AddressSanitizer 下,它会用大致相同的论点对你大喊大叫。