Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Cygwin 1.7.28中的mkstemp()和fdopen()_C++_C_Gcc_Cygwin - Fatal编程技术网

C++ Cygwin 1.7.28中的mkstemp()和fdopen()

C++ Cygwin 1.7.28中的mkstemp()和fdopen(),c++,c,gcc,cygwin,C++,C,Gcc,Cygwin,在使用GNU GCC 4.8.2在Cygwin(1.7.28-2,64位)下构建一些基于C++的代码的过程中,我遇到了以下错误: ... 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);

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

...
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+");
...
无法编译的特定代码块是:

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;
}
以下是我正在使用的GCC版本:

$ 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)
问题

  • Cygwin的GCC 4.8.2中是否支持
    mkstemp()
    fdopen()

  • 如果没有,我是否可以添加一个包或一个相对容易编译的库来添加对这些函数的支持

  • 如果没有,我是否可以利用
    mkstemp()
    fdopen()
    的替代方案在Cygwin下复制它们的功能

  • 可能的修复

    以下是此函数的修改版本:

    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函数的方法,如果可以的话,我愿意使用它们。谢谢你的建议。

    我的朋友文森特制作了一个与Cygwin一起使用的简单版本

    它可能不涵盖所有情况

    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    
    # include <windows.h>
    # include <io.h>
    
    int mkstemp(char *template)
    {
        char *temp;
    
        temp = _mktemp(template);
        if (!temp)
            return -1;
    
        return _open(temp, _O_CREAT | _O_TEMPORARY | _O_EXCL | _O_RDWR, _S_IREAD | _S_IWRITE);
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    int mkstemp(字符*模板)
    {
    字符*温度;
    温度=_mktemp(模板);
    如果(!temp)
    返回-1;
    返回打开状态(临时、创建、临时、不包括RDWR、IREAD、IWRITE);
    }
    

    至于
    fdopen
    ,我不确定。我必须做一些研究/思考。

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

    $ 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
    中,如果定义了
    \uuu STRICT\u ANSI\uuuu
    ,则会拒绝
    mkstemp()
    和一些其他函数的声明,例如当我们使用编译时标志
    -ANSI
    -std=c++11

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

    < C++标题>代码> <代码>和<代码> <代码>都包含了 STDLIB .H< /COD>和<代码> STDIO .H/COD>这两个函数的头和左声明(除此之外)到这两个标题。因此,如果我们使用
    -ansi
    和/或
    -std=c++11
    ,那么这两个函数将不会被声明,我们将得到编译错误

    对于玩具代码示例来说,似乎有效的解决方案是在编译之前取消定义
    \uuuu STRICT\u ANSI\uuu

    $ g++ -std=c++11 -U__STRICT_ANSI__ foo.cpp
    

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

    最近我在编译git crypt时遇到了同样的问题。上述答案中的解决方案有效,但它必须通过“make”而不是通过“g++”进行部署,如下所示:

    make CXXFLAGS="-U__STRICT_ANSI__ -std=c++11"
    

    Cygwin有一套类似Linux的操作系统。然而,C++上的Linux,<代码> .GuuuSoist是无条件定义的,基本上否定了所有这样的守卫。在CygWin上,我们不这样做,也就是说,你实际上必须尊重C++上各种标志的含义。 如前所述,使用任何
    -std=c++*
    标志将定义
    \uuuu STRICT\u ANSI\uuu
    ,这是由宏识别的。在命令行上取消定义是不正确的。相反,可以为您希望使用的函数定义正确的文档标记(在这种情况下,
    -D_POSIX_C_SOURCE=200809L
    应涵盖这两个),或者使用
    -std=gnu++*
    标记(顺便说一句,这些标记不定义
    \u gnu SOURCE
    )来不声明符合ANSI标准

    make CXXFLAGS="-U__STRICT_ANSI__ -std=c++11"