gpt4 book ai didi

c++ - 这个 UUID 生成代码有问题吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:04:25 26 4
gpt4 key购买 nike

所以我有一些代码需要使用 UUID 作为数据库 ID。为了简单起见,我使用了 v4(随机),而且我没有看到任何真正的理由使用任何其他随机性较低的 UUID 版本。我的 UUID 类大致定义如下(简化):

class uuid {
public:
static uuid create_v4();
public:
// cut out for simplification...
public:
uint8_t bytes[16];
};

实际的生成代码如下所示:

namespace {

uint32_t rand32() {
// we need to do this, because there is no
// gaurantee that RAND_MAX is >= 0xffffffff
// in fact, it is LIKELY to be 0x7fffffff
const uint32_t r1 = rand() & 0x0ff;
const uint32_t r2 = rand() & 0xfff;
const uint32_t r3 = rand() & 0xfff;
return (r3 << 20) | (r2 << 8) | r1;

}

}

uuid uuid::create_v4() {

static const uint16_t c[] = {
0x8000,
0x9000,
0xa000,
0xb000,
};

uuid uuid;

const uint32_t rand_1 = (rand32() & 0xffffffff);
const uint32_t rand_2 = (rand32() & 0xffff0fff) | 0x4000;
const uint32_t rand_3 = (rand32() & 0xffff0fff) | c[rand() & 0x03];
const uint32_t rand_4 = (rand32() & 0xffffffff);

uuid.bytes[0x00] = (rand_1 >> 24) & 0xff;
uuid.bytes[0x01] = (rand_1 >> 16) & 0xff;
uuid.bytes[0x02] = (rand_1 >> 8 ) & 0xff;
uuid.bytes[0x03] = (rand_1 ) & 0xff;

uuid.bytes[0x04] = (rand_2 >> 24) & 0xff;
uuid.bytes[0x05] = (rand_2 >> 16) & 0xff;
uuid.bytes[0x06] = (rand_2 >> 8 ) & 0xff;
uuid.bytes[0x07] = (rand_2 ) & 0xff;

uuid.bytes[0x08] = (rand_3 >> 24) & 0xff;
uuid.bytes[0x09] = (rand_3 >> 16) & 0xff;
uuid.bytes[0x0a] = (rand_3 >> 8 ) & 0xff;
uuid.bytes[0x0b] = (rand_3 ) & 0xff;

uuid.bytes[0x0c] = (rand_4 >> 24) & 0xff;
uuid.bytes[0x0d] = (rand_4 >> 16) & 0xff;
uuid.bytes[0x0e] = (rand_4 >> 8 ) & 0xff;
uuid.bytes[0x0f] = (rand_4 ) & 0xff;

return uuid;
}

这对我来说看起来是正确的,但我最近从数据库中收到一个错误,说我尝试插入的 UUID 是重复的。由于这应该是极不可能的,因此我必须假设我的代码可能存在问题。所以有人看到什么不对吗?我的随机 UUID 生成是否不够随机?

注意:我不能使用 boost 的随机数生成或其 UUID 库。我希望我可以,但是我被安装了特定版本库的特定系统所束缚,并且几乎不可能获得足够新的 boost 版本来拥有这些功能。

最佳答案

代码对我来说似乎是合理的。正如评论中所提到的,关于 rand() 是否是这项任务的一个好的选择存在一些问题,但是假设正在更新版本的库,您对它的使用似乎是一种生成 32 位数据的合理方法用于确保低位与高位一样随机(也在您的评论中提到)。

因此,只要 rand() 函数工作得还算不错,您就不太可能得到一个拷贝。所以我的猜测是有一种不同的失败。想到的一些可能性:

  1. time(0) 失败。这似乎极不可能。如果它返回 -1 以指示两次不同运行中的错误,那么它可能会导致问题。然而,它应该能够失败的唯一方法是如果给它一个无效的地址(这里绝对不是这种情况)。
  2. 多线程使用。我不认为 rand() 是线程安全的。如果在多线程情况下使用此代码,可能会导致意外行为。
  3. Cron 正在造成困难。如果工作站上的时钟不准确并且它被自动设置(例如,通过 rdate)以与某些服务器同步,那么它可能会导致 cron 作业在特定时间重复。我能够简单地通过创建一个 cron 作业来模仿这种行为,每分钟将当前日期转储到一个文件中,然后重复设置日期……它最终将相同的日期/时间(到第二个)写入文件不止一次。使用一秒分辨率的时间函数,这很容易导致重复的种子。
  4. 将 UUID 写入数据库的代码不正确。即使 UUID 生成器运行良好,也可能存在将相同 UUID 写入数据库两次的不同错误。

只是胡乱猜测。其中,第三个是我最喜欢的,但如果我正在审查自己的代码,我会首先怀疑第 4 个。

关于c++ - 这个 UUID 生成代码有问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12322985/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com