C++在全局命名空间中找不到非标准 C 函数

C++ can't find non-standard C functions in global namespace

本文关键字:非标准 函数 找不到 全局 命名空间 C++      更新时间:2023-10-16

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

error C2039: 'strdup' : is not a member of '`global namespace''    ...ACE_wrappersaceOS_NS_string.inl    222
...
error C2065: 'O_WRONLY' : undeclared identifier                    ...ACE_wrappersaceOS_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作为最早的东西并没有改变什么。

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

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

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

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

">许多标准C函数和符号未定义">

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

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

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

有了Mark B的注释,促使我查看12 MiB的预处理器输出,我能够解决它。在string.h中,定义strdup的代码段如下所示:

#if     !__STDC__
...
_Check_return_ _CRT_NONSTDC_DEPRECATE(_strdup) _CRTIMP char * __cdecl strdup(_In_opt_z_ const char * _Src);

碰巧这个项目定义了__STDC__符号,这导致许多非标准的C-but-still-in-the--standard-library(感谢Robφ挑剔但没有解决问题)功能完全消失。

我知道它们被弃用了,我收到了很多警告。但正如所指出的,我并没有为第三方库维护特定于项目的补丁,我们使用这些补丁只是为了在更新它们时再次获得同样的乐趣。

如果我正确理解VS,strdup等函数名称现在已经不推荐使用了(我认为这与POSIX不兼容)。你应该使用带下划线的版本。

当我遇到这种情况时,我进行了全局搜索和替换,因为这似乎是一件明智的事情,并使源代码在未来保持良好的状态(VS 2012已经发布了!:))。