【问题标题】:When are global static const variables being initialized?什么时候初始化全局静态常量变量?
【发布时间】:2023-03-22 20:03:01
【问题描述】:

我试图在网站上搜索这个问题,但没有准确找到这个问题,尽管这个主题正在讨论很多......

我在一个 cpp 文件中有这个声明,而不是在任何函数中:

static const char* gText = "xxxxxxxxxxx";

虽然它具有固定大小,但当我尝试将其复制到另一个 char* 变量时,我从静态分析工具 (Klocwork) 收到警告 - 关于可能超出范围违规:

char xText[32];
SecureZeroMemory(xText, 32);
memcpy(xText, gText, strlen(gText));

是误报还是全局变量稍后被初始化?

谢谢!

【问题讨论】:

  • KLOCWORKS 指的是哪一行?
  • 看起来是误报。
  • 顺便说一句,指针本身不是const,所以,可以改成指向另一个更长的字符串
  • @Sellibitze,你是对的。可能这就是为什么 KW 毕竟抱怨它的原因。谢谢!

标签: c++ static constants global-variables static-analysis


【解决方案1】:

这是一个误报。 strlen 可能被抽象为返回一个未知的正数,因此在分析 memcpy(dest,src,strlen(src)); 模式时,分析器不会意识到只要 src 是一个格式良好的字符串,副本的读取部分是安全的。

如果您使用strcpy,分析器可能会得出结论认为在这种情况下没问题。你有理由不这样做吗?函数 strcpy 被认为是“不安全的”,但你的 memcpy(..,src,strlen(src)) 也很不安全。

编辑:此外,sellibitze 在 cmets 中提出了一个非常好的观点:原始代码中的 const 属性仅适用于 gText 指向的字符,而不适用于 gText 本身。

【讨论】:

  • 谢谢。 strcpy 不能解决这个问题,但我只在长度不大于边界时才进行复制。谢谢!
【解决方案2】:

我认为这不是误报。有人可能会出现并更改 gText 的长度而没有意识到它不能超过 32 个字符的潜在风险。我肯定会在 memcpy 之前进行某种检查,以确保不会出现缓冲区溢出。

例如

char xText[32];
SecureZeroMemory(xText, 32);
size_t lenToCopy = MIN(strlen(gText), 32);
memcpy(xText, gText, lenToCopy);

我也想用一个常数来代替幻数 32。

【讨论】:

  • 我评论了一个非常相似的评论,答案被其作者删除。所以我不会再重复同样的事情,但是既然你已经决定使用gText 的所有可能值,为什么假设gText 是一个格式正确的字符串(在字符上调用strlen 是非法的数组不是格式正确的字符串)?
  • 如果xText 应该在复制后包含一个格式良好的字符串,那么MIN(..,32) 中的32 应该是31
  • @Pascal:对我来说,使用 memcpy 而不是字符串函数意味着其目的是获得将被视为固定大小的字节块而不是 C 字符串的东西。这就是我将限制设置为 32 的原因。如果我试图复制一个字符串,我会使用 strncpy (或等效的)来做到这一点 - 或者因为这是 C++ std::string。
  • 谢谢。但是,作为 BKM 规则,不要进行部分复制。绝不。它可能会导致奇怪的结果,很难找到根本原因。返回错误代码\改为抛出异常。
  • @IUnknownPointer:JeremyP 规则:始终坚持严格的规则是无法成功完成编程的。你需要使用智能。它们不是规则,它们更像是指导方针。在这种情况下,对于您的意图没有任何线索。也许你有一些理由只希望字符串的前 32 个字符放入某些网络协议的标头中。
猜你喜欢
  • 1970-01-01
  • 2012-02-01
  • 2014-08-06
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多