fclose在android和linux上的工作方式不同

And*_*sev 5 linux android fclose android-ndk freopen

以下计划:

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main() {
  fclose( stderr );
  printf( "%d\n", fileno( stderr ) );
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

显示-1在Ubuntu 11.04和2对ICS 4.0.3模拟器.找不到有关此问题的任何信息 - 我可以在两个平台上使此代码的工作类似吗?freopenstderr有同样的问题.

更新:

以前的小程序演示了我遇到的实际问题的原因:如果我尝试freopen stderr在不存在的目录中存档,在linux stderr上关闭但在android上它保持打开状态!甚至更多 - 如果我在这个打开的stderr文件中写smth 然后fopen在其他文件stderr上写,我打印的文本将写入此打开的文件.

那么,这个程序:

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

# define LOGD( ... ) printf( __VA_ARGS__ ); printf( "\n" )

# ifdef ANDROID
#   define HOMEDIR "/data/data/com.myapp/" // for android
# else
#   define HOMEDIR "/home/darkmist/" // for linux
# endif

# define _T( x ) x

void TestFreopen_mkdir() {
  int mkdirres = mkdir( HOMEDIR "1.d", 0777 );
  LOGD(_T("TestFreopen mkdirres=0x%08x"),mkdirres);
}

void TestFreopen() {
  LOGD(_T("TestFreopen begin"));

  LOGD(_T("TestFreopen stderr=0x%08x"),fileno(stderr));
  fprintf(stderr,"fprintf_1 to stderr\n");

  // TestFreopen_mkdir(); // case 1

  if ( NULL == freopen( HOMEDIR "1.d/1", "w", stderr ) ) {
    LOGD( "freopen failed" );
    if ( -1 != fileno( stderr ) ) {
      fclose( stderr );
      LOGD( "freopen closed" );
    }
  }

  LOGD(_T("TestFreopen stderr=0x%08x"),fileno(stderr));
  fprintf(stderr,"fprintf_2 to stderr\n");

  TestFreopen_mkdir(); // case 2

  FILE* fopen_file = fopen( HOMEDIR "1.d/2", _T( "wb" ) );

  LOGD(_T("TestFreopen fopen_file=0x%08x"),fileno(fopen_file)); // same as for reopened stderr!!

  fprintf(stderr,"fprintf_3 to stderr\n");
  fprintf(fopen_file,"fprintf_1 to fopen_file\n");
  fflush(fopen_file);

  LOGD(_T("TestFreopen end"));
}

int main() {
  TestFreopen();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在linux上显示:

$ ./a.out
TestFreopen begin
TestFreopen stderr=0x00000002
fprintf_1 to stderr
freopen failed
TestFreopen stderr=0xffffffff
TestFreopen mkdirres=0x00000000
TestFreopen fopen_file=0x00000002
TestFreopen end

$ cat ~/1.d/2 
fprintf_1 to fopen_file
Run Code Online (Sandbox Code Playgroud)

这在android上:

$ adb push ./a.out /data/data/com.myapp
573 KB/s (34635 bytes in 0.058s)

$ adb shell run-as com.myapp /data/data/com.myapp/a.out
TestFreopen begin
TestFreopen stderr=0x00000002
fprintf_1 to stderr
freopen failed
freopen closed
TestFreopen stderr=0x00000002
TestFreopen mkdirres=0x00000000
TestFreopen fopen_file=0x00000002
TestFreopen end

$ adb shell run-as com.myapp cat /data/data/com.myapp/1.d/2
fprintf_3 to stderr
fprintf_1 to fopen_file
Run Code Online (Sandbox Code Playgroud)

Chr*_*ton 10

在我看来,你期望正式声明的文件指针在其关闭之后的未定义行为在具有非常不同的C库的设备上是相同的.

一旦以一种旨在失败的方式调用freopen(),将来尝试使用该文件指针就不能依赖于获得一致的结果.

你发现了一些有趣的结果,剩下的碎片仍然可以用于意外的结果,但问题不在于它们不会导致某种异常,问题是你试图在一种语言中使用无效的文件指针并不宣传自己有保障措施.

问题不在于系统,而在于您的程序滥用系统.


Ric*_*ell 4

在任何平台上,关闭 stderr 后尝试使用 stderr 都没有任何意义。

\n

  • 答案还是一样。一旦关闭了流,您就不能将指针用于任何目的。C99 s7.19.3 para 4 明确了这一点:关闭流后指针变得不确定。 (5认同)