首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Cygwin 1.7.28中的mkstemp()和fdopen()

Cygwin 1.7.28中的mkstemp()和fdopen()
EN

Stack Overflow用户
提问于 2014-02-10 22:21:15
回答 4查看 2.9K关注 0票数 6

在用GNU GCC 4.8.2在Cygwin (1.7.28-2,64位)下构建一些基于C++的代码时,我遇到了以下错误:

代码语言:javascript
复制
...
SortDetails.cpp: In function ‘FILE* create_tmpfile(const char*, char**)’:
SortDetails.cpp:127:20: error: ‘mkstemp’ was not declared in this scope
   fd = mkstemp(tmpl);
                    ^
SortDetails.cpp:133:24: error: ‘fdopen’ was not declared in this scope
   fp = fdopen(fd, "wb+");
...

无法编译的特定代码块是:

代码语言:javascript
复制
FILE *
create_tmpfile(char const* path, char** fileName)
{
  FILE* fp;
  int fd;
  char* tmpl;

  if ( path == NULL )
      {
          fileName = NULL;
          return tmpfile();
      }

  tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam);
  strcpy(tmpl, path);
  strcpy(tmpl+strlen(path), "/sb.XXXXXX");
  fd = mkstemp(tmpl);                        /* <----- here... */
  if(fd == -1)
      {
          fprintf(stderr, "unable to create temp file!\n");
          return NULL;
      }
  fp = fdopen(fd, "wb+");                    /* <----- ...and here */
  *fileName = (char*)malloc(strlen(tmpl) + 1);
  strcpy(*fileName, tmpl);
  free(tmpl);
  return fp;
}

( malloc的结果正在转换,因为这段代码位于一个更大的基于C++的项目中。)

回归

此代码在Linux主机上编译并成功地与GNU GCC 4.8.x以及在OS下的Clang/+ 5.0一起编译和工作。

环境

我正在使用以下版本的Cygwin:

代码语言:javascript
复制
$ uname -a
CYGWIN_NT-6.1 CygFoo-PC 1.7.28(0.271/5/3) 2014-02-09 21:06 x86_64 Cygwin

下面是我所用的GCC的版本:

代码语言:javascript
复制
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-cygwin/4.8.2/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: /cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.2-2/src/gcc-4.8.2/configure --srcdir=/cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.2-2/src/gcc-4.8.2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/libexec --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target=x86_64-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --disable-__cxa_atexit --with-dwarf2 --with-tune=generic --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libgomp --disable-libitm --enable-libquadmath --enable-math-support --enable-libssp --enable-libada --enable-libgcj-sublibs --disable-java-awt --disable-symvers --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib
Thread model: posix
gcc version 4.8.2 (GCC)

问题

  1. GCC 4.8.2对Cygwin的mkstemp()fdopen()是否有支持?
  2. 如果没有,是否有我可以添加的包或相对容易编译的库来添加对这些函数的支持?
  3. 如果没有,我是否可以使用mkstemp()fdopen()的替代方案来复制它们在Cygwin下的功能?

可能修复

下面是这个函数的修改版本:

代码语言:javascript
复制
FILE *
create_tmpfile(char const* path, char** fileName)
{
  FILE* fp;
  char* tmpl;

  if ( path == NULL )
      {
          fileName = NULL;
          return tmpfile();
      }

#if defined(__CYGWIN__) && !defined(_WIN32)
  const char *cygwinPrefix = "/sb.";
  const char *cygwinTmpDir = "/tmp";
  char *cygwinTmplSuffix = (char *)malloc(1 + L_tmpnam);
  tmpnam(cygwinTmplSuffix);
  tmpl = (char *)malloc(1 + strlen(path) + strlen(cygwinPrefix) + strlen(cygwinTmplSuffix + strlen(cygwinTmpDir) + 1));
  strcpy(tmpl, path);
  strcpy(tmpl+strlen(path), cygwinPrefix);
  strcpy(tmpl+strlen(path)+strlen(cygwinPrefix), cygwinTmplSuffix + strlen(cygwinTmpDir) + 1);
  fp = fopen(tmpl, "wbx+"); /* we add the 'x' extension to apply the O_EXCL flag, to avoid a security hole described in the GNU C library docs */
  free(cygwinTmplSuffix);
#else
  tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam);
  strcpy(tmpl, path);
  strcpy(tmpl+strlen(path), "/sb.XXXXXX");
  int fd = mkstemp(tmpl);
  if(fd == -1)
      {
          fprintf(stderr, "unable to create temp file!\n");
          return NULL;
      }
  fp = fdopen(fd, "wb+");
#endif
  *fileName = (char*)malloc(strlen(tmpl) + 1);
  strcpy(*fileName, tmpl);
  free(tmpl);
  return fp;
}

这太丑了。如果有使用POSIX函数的方法,如果可以的话,我想使用它们。谢谢你的建议。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-02-13 09:19:42

在Cygwin上用g++ 4.8.2编译时,我将宏的扩展记录在三种情况下:

代码语言:javascript
复制
$ g++ -std=c++11 -E -Dd foo.cpp > foo.log.c++11
$ g++ -ansi -E -Dd foo.cpp > foo.log.ansi
$ g++ -E -Dd foo.cpp > foo.log.noFlag

比较日志是有用的。-std=c++11-ansi案例中存在“漏洞”,而包含mkstemp()声明的块出现在“无标记”情况下。这让我集中在不同处理的头的部分上。

在文件/usr/include/stdlib.h中,如果定义了mkstemp()和其他一些函数的声明,例如当我们使用编译时标志-ansi-std=c++11时,__STRICT_ANSI__将被拒绝。

同样,在/usr/include/stdio.h文件中,出于同样的原因,fdopen()的声明将被跳过。

C++标头<cstdlib><cstdio>都包含stdlib.hstdio.h头,并将这两个函数的声明保留到这两个标头。因此,如果我们使用-ansi和/或-std=c++11,那么这两个函数将不会被声明,并得到编译错误。

似乎适用于玩具代码示例的解决方案是在编译之前取消定义__STRICT_ANSI__

代码语言:javascript
复制
$ g++ -std=c++11 -U__STRICT_ANSI__ foo.cpp

目前还不清楚这会产生什么副作用,但从googling来看,这似乎是一个常见的问题,也是需要针对Cygwin的其他开发人员应用的一个常见的修复方法。

票数 6
EN

Stack Overflow用户

发布于 2019-08-14 16:24:36

Cygwin有一套类似Linux的特征测试宏。但是,在使用C++的Linux上,_GNU_SOURCE是无条件定义的,本质上否定了所有这些保护。在Cygwin上,我们没有这样做,这意味着您实际上也必须尊重C++上各种标志的含义。

如前所述,使用任何-std=c++*标志都将定义__STRICT_ANSI__,这是由宏识别的。在命令行中取消定义是不正确的。相反,要么为您希望使用的函数定义正确的文档标记(在本例中,-D_POSIX_C_SOURCE=200809L应该同时涵盖这两个函数),要么使用-std=gnu++*标志代替(顺便说一句,它不定义_GNU_SOURCE)以不声明ANSI遵从性。

票数 2
EN

Stack Overflow用户

发布于 2019-04-11 22:19:32

最近,我正在编译git-crypt,也遇到了同样的问题。上述答案中的解决方案起作用了,只是必须通过'make‘而不是'g++’来部署它,如下所示:

代码语言:javascript
复制
make CXXFLAGS="-U__STRICT_ANSI__ -std=c++11"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21689124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档