如何在 C++ 中生成 UUID,而不使用 boost 库?
Posted
技术标签:
【中文标题】如何在 C++ 中生成 UUID,而不使用 boost 库?【英文标题】:How can I generate UUID in c++, without using boost library? 【发布时间】:2014-08-13 10:59:56 【问题描述】:我想为我的应用程序生成 UUID 以区分我的应用程序的每次安装。我想在不支持 boost 库的情况下使用 C++ 生成这个 UUID。如何使用其他一些开源库生成 UUID?
注意:我的平台是windows
【问题讨论】:
Qt. 在windows上你可以使用UuidCreate
它在rpc.h
。例如:nogeekhere.blogspot.in/2008/07/…
加一表示“不使用 boost”
【参考方案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 <rpc.h>
对我来说是必要的(而不是 #include <windows.h>
)以上是关于如何在 C++ 中生成 UUID,而不使用 boost 库?的主要内容,如果未能解决你的问题,请参考以下文章