【问题标题】:How can I generate UUID in c++, without using boost library?如何在 C++ 中生成 UUID,而不使用 boost 库?
【发布时间】:2014-08-13 10:59:56
【问题描述】:

我想为我的应用程序生成 UUID 以区分我的应用程序的每次安装。我想在不支持 boost 库的情况下使用 C++ 生成这个 UUID。如何使用其他一些开源库生成 UUID?

注意:我的平台是windows

【问题讨论】:

标签: c++ uuid


【解决方案1】:

这是一个使用随机库在c++中基于字符串生成唯一uuid的函数,而不使用boost库

std::string generate_uuid(std::string &seedstring)
{
    auto sum = std::accumulate(seedstring.begin(), seedstring.end(), 0);

    std::mt19937                    gen(sum);
    std::uniform_int_distribution<> dis(0, 15);
    std::uniform_int_distribution<> dis2(8, 11);

    std::stringstream ss;
    ss.clear();
    int i;
    ss << std::hex;
    for (i = 0; i < 8; i++) {
        ss << dis(gen);
    }
    ss << "-";
    for (i = 0; i < 4; i++) {
        ss << dis(gen);
    }
    ss << "-4";
    for (i = 0; i < 3; i++) {
        ss << dis(gen);
    }
    ss << "-";
    ss << dis2(gen);
    for (i = 0; i < 3; i++) {
        ss << dis(gen);
    }
    ss << "-";
    for (i = 0; i < 12; i++) {
        ss << dis(gen);
    };
    cout << "uuid is" << ss.str() << endl;
    return ss.str();
}
this function will generate same uuid until seedstring value is same.

【讨论】:

    【解决方案2】:

    您可以使用我为此开发的rst C++ 库:

    #include "rst/guid/guid.h"
    
    std::string guid = rst::Guid().AsString();
    
    // Performs no allocations.
    std::cout << rst::Guid().AsStringView().value() << std::endl;
    

    【讨论】:

    • 您链接的 GitHub 项目似乎是您自己的。如果情况,那么您必须明确披露该事实,否则您的帖子可能会被视为垃圾邮件。
    【解决方案3】:

    2021年,我建议使用单头库stduuid。它是跨平台的,不会引入任何不需要的依赖项。

    从项目的 github 页面下载uuid.h,然后一个最小的工作示例是:

    #include <iostream>
    #include <string>
    
    #define UUID_SYSTEM_GENERATOR
    #include "uuid.h"
    
    int main (void) {
        std::string id = uuids::to_string (uuids::uuid_system_generator{}());
        std::cout << id << std::endl;
    }
    

    有关各种选项和生成器的更多详细信息和文档,请参阅项目的 github 页面。

    【讨论】:

    • 这个repo测试好了吗?
    【解决方案4】:

    如果您使用的是现代 C++,就可以了。

    #include <random>
    #include <sstream>
    
    namespace uuid {
        static std::random_device              rd;
        static std::mt19937                    gen(rd());
        static std::uniform_int_distribution<> dis(0, 15);
        static std::uniform_int_distribution<> dis2(8, 11);
    
        std::string generate_uuid_v4() {
            std::stringstream ss;
            int i;
            ss << std::hex;
            for (i = 0; i < 8; i++) {
                ss << dis(gen);
            }
            ss << "-";
            for (i = 0; i < 4; i++) {
                ss << dis(gen);
            }
            ss << "-4";
            for (i = 0; i < 3; i++) {
                ss << dis(gen);
            }
            ss << "-";
            ss << dis2(gen);
            for (i = 0; i < 3; i++) {
                ss << dis(gen);
            }
            ss << "-";
            for (i = 0; i < 12; i++) {
                ss << dis(gen);
            };
            return ss.str();
        }
    }
    

    【讨论】:

    • 我认为值得注意的是,此输出的格式类似于 guid,但不足以成为 guid。 cplusplus.com/reference/random/mt19937 std::mt19937 具有 32 位随机性,或 4E9 组合。真正的 guid 具有 128 位随机性,或 3E38 种组合。真正的 guid 会更加随机 (bil bil bil)x。 mt19937->mt19937_64 将是一种改进,即 64 位随机性或 1.8E19 组合,但就随机性期望而言,仍然不是指导。
    • 一题:32位随机性+32位随机性+....+32位随机性不等于128位随机性???
    • @RaulLuna 不,因为这是伪随机数生成器,所以所有后续调用都依赖于先前的调用。就像从 int16 制作 SHA256 仍然会产生 65,000 个唯一哈希,而不是 2**256。 std::mt19937 内部包含更多状态位,但这取决于初始状态,因此子序列非常不清楚。真正的 UUID 在唯一性方面要可靠得多。
    • PRNG 的状态足够大(19937 位),但它完全由 random_device (rd()) 生成的 32 位值播种,因此此函数只能生成 2^32可能的 uuid。否决,不要使用这个或任何类似的答案,否则您可能会引入安全问题,请参阅this question
    【解决方案5】:

    如果你只是想要一些随机的东西,我写了这个小函数:

    string get_uuid() {
        static random_device dev;
        static mt19937 rng(dev());
    
        uniform_int_distribution<int> dist(0, 15);
    
        const char *v = "0123456789abcdef";
        const bool dash[] = { 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
    
        string res;
        for (int i = 0; i < 16; i++) {
            if (dash[i]) res += "-";
            res += v[dist(rng)];
            res += v[dist(rng)];
        }
        return res;
    }
    

    【讨论】:

    • @Nina 不保证,但你中彩票后被闪电击中的可能性比发生碰撞的可能性更大。
    【解决方案6】:

    传统上,UUID 只是机器的 MAC 地址,加上自西方采用公历以来的 100 纳秒间隔数。所以写一个 C++ class 来为你做这件事并不难。

    【讨论】:

    • 但是我需要根据随机数生成 UUID(类型 4)#Paul。我不能使用 C++ 中可用的普通 rand() 函数。这就是我尝试库文件的原因。
    • 有几个versions and variants of UUIDs;您的回答仅涵盖版本 1。
    • @user3732956:如果您要执行的操作随机 UUID,为什么不能使用 rand() 或任何其他(伪)随机函数?
    • 是的,去伪随机函数,我想我应该去库文件,对吧。这就是为什么我更喜欢直接使用 UUID 库文件。
    • 这种风格的 UUID(类型 1)已被弃用,取而代之的是不泄露 PII 的 UUID。
    【解决方案7】:

    ossp-uuid 库可以生成 UUID 并具有 C++ 绑定。

    使用起来似乎极其简单:

    #include <uuid++.hh>
    #include <iostream>
    
    using namespace std;
    
    int main() {
            uuid id;
            id.make(UUID_MAKE_V1);
            const char* myId = id.string();
            cout << myId << endl;
            delete myId;
    }
    

    请注意,它分配并返回一个 C 风格的字符串,调用代码必须解除分配以避免泄漏。

    另一种可能性是 libuuid,它是 util-linux 包的一部分,可从ftp://ftp.kernel.org/pub/linux/utils/util-linux/ 获得。任何 Linux 机器都已经安装了它。它没有 C++ API,但仍可使用 C API 从 C++ 调用。

    【讨论】:

    • 关于调用 uuid 的 string() 函数的注意事项,它分配的内存必须由调用代码释放!在上面的答案中,调用 id.string() 将 char* 返回到新分配的内存,而不是一个不错的 std::string (通过析构函数/RAII 管理其内存)。所以上面的代码有内存泄漏。最好设置 char* str = id.string() 然后在 str 上调用 delete 一旦完成使用它。
    • @jCuga 好伤心,我什至没有注意到!谢谢,已更新答案。
    【解决方案8】:

    如cmets中所说,可以使用UuidCreate

    #pragma comment(lib, "rpcrt4.lib")  // UuidCreate - Minimum supported OS Win 2000
    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        UUID uuid;
        UuidCreate(&uuid);
        char *str;
        UuidToStringA(&uuid, (RPC_CSTR*)&str);
        cout<<str<<endl;
        RpcStringFreeA((RPC_CSTR*)&str);
        return 0;
    }
    

    【讨论】:

    • #Yuval,我应该下载 rpcrt4.lib 并将该库文件保存在 lib 文件夹中吗?或者 rpcrt4.lib 在 Windows 中可用。不好意思问这么傻的问题
    • @PURE 这个库包含在 Visual Studio 的安装中
    • 或者使用 CoCreateGuid,它是 UuidCreate 的包装器。
    • 请注意,要链接 rpcrt4.lib,您必须打开项目的属性,转到配置属性 -> 链接器 -> 命令行,然后在附加选项框中键入 Rpcrt4.lib。
    • #include &lt;rpc.h&gt; 对我来说是必要的(而不是 #include &lt;windows.h&gt;
    猜你喜欢
    • 2011-03-15
    • 2012-01-18
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    相关资源
    最近更新 更多