【问题标题】:C++ can't find non-standard C functions in global namespaceC++ 在全局命名空间中找不到非标准 C 函数
【发布时间】:2012-11-16 10:12:46
【问题描述】:

我们有一个相当大的 C++ 项目,我现在正在迁移到 VS2010 并在此过程中更新一些库。到目前为止,一切都构建得很好,除了我得到(对我来说)非常奇怪的错误,其中显然没有定义许多(edit: 非)标准 C 函数和符号:

error C2039: 'strdup' : is not a member of '`global namespace''    ...\ACE_wrappers\ace\OS_NS_string.inl    222
...
error C2065: 'O_WRONLY' : undeclared identifier                    ...\ACE_wrappers\ace\OS_NS_unistd.inl    1057
...

这对我来说会影响以下功能和符号:

strdup      getcwd      O_WRONLY
putenv      swab        O_TRUNC
access      unlink      S_IFDIR
chdir       mkdir       S_IFREG
rmdir       tempnam     O_RDONLY
isascii

我试验过的 ACE 包含文件中的一部分是 strdup 部分,如下所示:

ACE_INLINE char *
ACE_OS::strdup (const char *s)
{
#  if (defined (ACE_LACKS_STRDUP) && !defined(ACE_STRDUP_EQUIVALENT)) \
  || defined (ACE_HAS_STRDUP_EMULATION)
  return ACE_OS::strdup_emulation (s);
#  elif defined (ACE_STRDUP_EQUIVALENT)
  return ACE_STRDUP_EQUIVALENT (s);
#  elif defined (ACE_HAS_NONCONST_STRDUP)
  return ::strdup (const_cast<char *> (s));
#else
  return ::strdup (s);
#  endif /* (ACE_LACKS_STRDUP && !ACE_STRDUP_EQUIVALENT) || ... */
}

上面和下面的其他函数有很多类似的部分,所有这些都编译得很好。

我的路径是最后一条,即return ::strdup (s);。如果我在 ::strdup 上按 F12,VS 会将我带到 C 标准库的 string.h 中的声明。

如果我删除它构建的命名空间限定符,尽管 IntelliSense 告诉我它现在是一个递归调用,所以它可能无法工作。如果我将命名空间更改为 std:: 我会收到大约 270 个更多错误,这一次来自其他几个项目。如果我将函数更改为 ::_strdup 它会构建。包括string.h 作为第一件事没有任何改变。

(注意:“它构建”是指“这个特定的编译器错误在那个位置消失了,但显然它仍然留下关于其他函数的错误。)

我在这里有点不知所措。我注意到许多大型库要么在标准库上构建自己的抽象,要么提供默认情况下不存在的东西,这就是 ACE 和 ImageMagick 已经发生冲突的地方(typedefing ssize_t 但定义不兼容) .由于我们引入了很多库(我现在也没有确切的概述),这很可能是另一个冲突,由错误的包含顺序和类似的事情引起。 ACE 中的相同包含在同一解决方案中的其他项目中显然可以正常工作,这一事实也暗示了这一点。

有人知道我至少可以在这里寻找什么吗? /showIncludes 的构建日志只有 24k 行,所以我看不到很多模式,除了 string.h 被包含在有问题的 ACE 标头之前。

我不想修改库源代码,因为如果我们更新到新版本,那只会再次咬我们。

【问题讨论】:

  • 在 C++ 中,它的正式名称是 &lt;cstring&gt;,而不是 &lt;string.h&gt;
  • 您可以使用其中任何一种,它们的区别在于函数是否出现在全局命名空间中并且仅 可能 出现在 std 中,或者它们是否出现在 std 中并且仅出现 也许在全局命名空间中。不过,这并没有什么不同。至少我是这么理解的。
  • @ipc - 正式 both &lt;cstring&gt;&lt;string.h&gt;&lt;cstring&gt; 需要将名称放入命名空间 std&lt;string.h&gt; 需要将名称放入全局命名空间。
  • 您是否尝试仅预处理代码并在结果输出中验证函数是否位于全局命名空间中(如果 &lt;string.h&gt; 意外包含在 namespace &lt;blah&gt; { 中怎么办?)跨度>
  • 从google搜索来看,VS支持ACE。也许您的解决方案缺少一些定义?可以从原始源下载VS解决方案文件吗?

标签: c++ c ace


【解决方案1】:

"许多标准 C 函数和符号没有定义"

strdup 不是标准的 C 函数。它是在 POSIX 中定义的,但不是在 C 或 C++ 中定义的。引用MSDN:

这些 POSIX 函数从 Visual C++ 2005 开始已被弃用。请改用符合 ISO C++ 标准的 _strdup、_wcsdup、_mbsdup。

在我看来,您列出的符号都不是标准 C 函数。

【讨论】:

  • 好的,您在技术上是正确的,并指出了部分根本原因,但这对解决问题没有任何帮助。
  • 我以前从未见过“符合 ISO C++ 标准”这个短语曾表示“由 Microsoft 制造”。
  • @Mike Seymour 这意味着因为它们在全局命名空间中并且以_ 开头,所以允许编译器使用这些名称。
【解决方案2】:

Mark B 的评论提示我查看 12 MiB 的预处理器输出,我能够解决它。在string.h 中,定义strdup 的sn-p 如下所示:

#if     !__STDC__

...

_Check_return_ _CRT_NONSTDC_DEPRECATE(_strdup) _CRTIMP char * __cdecl strdup(_In_opt_z_ const char * _Src);

碰巧这个项目定义了__STDC__ 符号,这导致了很多非标准C-但仍然在-C-标准库中(谢谢,Robφ sub> 用于吹毛求疵但不解决问题)功能完全消失。

我知道它们已被弃用,我收到很多警告告诉我。但如前所述,我不会为我们使用的第 3 方库维护项目特定的补丁,只是为了在更新它们时再次享受同样的乐趣。

【讨论】:

    【解决方案3】:

    如果我正确理解 VS,strdup 等函数名称现在已被弃用(我认为不符合 POSIX)。您应该使用带下划线的版本。

    当这发生在我身上时,我进行了全局搜索和替换,因为这似乎是一件明智的事情,并且可以使源代码保持良好状态以备将来使用(VS 2012 已经发布!:))。

    【讨论】:

    • 只是不是我在使用它们,而是另一个库。
    猜你喜欢
    • 2019-11-15
    • 2019-07-16
    • 1970-01-01
    • 2016-03-14
    • 2017-05-31
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多