标签: stdio

防止包含stdio.h(或其他标准头文件)

我使用的代码库历史上曾经有意地试图避免依赖于stdio.h爬行.它有自己的打印格式和机制,那些应该用来代替printf等.

但是有人经常会添加一个依赖项,必须引起注意并被删除.所以我试着为最简单的情况发出警报:

#if !defined(NDEBUG)
   void printf(float dont_link_with_stdio_h);
#endif
Run Code Online (Sandbox Code Playgroud)

gcc人员似乎一直在思考如何阻止容易出错,因为如果你这样做有一个有用的信息......无论你是否包括在内<stdio.h>.

内置函数'printf'的冲突类型

有一种方法可以关闭此警告(-fno-builtin).并且有各种各样的方法可以做一些事情,例如过滤掉你不想去的东西的符号转储......

但有没有一个简单的非警告(如果你没有包括stdio.h)的方式提醒某人他们已经引入了不需要的printf用法?

c stdio

10
推荐指数
1
解决办法
268
查看次数

在C中尝试和真正的简单文件复制代码?

这看起来像一个简单的问题,但我在这里找不到类似的东西.

由于C中没有文件复制功能,我们必须自己实现文件复制,但我不喜欢重新发明轮子,即使是那样的琐碎事情,所以我想问云:

  1. 您建议使用fopen()/ fread()/ fwrite()进行文件复制的代码是什么?
    • 您建议使用open()/ read()/ write()进行文件复制的代码是什么?

此代码应该是可移植(在Windows/MAC/LINUX/BSD/QNX/younameit),稳定的,经过时间考验的,速度快,内存使用效率等进入特定系统的内部挤出一些性能是值得欢迎的(就像得到文件系统的簇大小) .

这似乎是一个微不足道的问题,但是,例如,CP命令的源代码不是10行C代码.

c file-io copy stdio

9
推荐指数
2
解决办法
1万
查看次数

无法使用fopen()打开文件

我一直在尝试打开文件和输出文本,但我一直在收到错误.所以我想我会从一开始就尝试打开文件.这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#define CORRECT_PARAMETERS 3

int main(void)
{
    FILE *file;
    file = fopen("TestFile1.txt", "r");
    if (file == NULL) {
        printf("Error");
    }
    fclose(file);
}
Run Code Online (Sandbox Code Playgroud)

当我运行该文件时,"错误"被打印到控制台,就是这样.TestFile1.txt与我的.exe位于同一位置.我该如何解决?

c file-io fopen stdio

9
推荐指数
5
解决办法
11万
查看次数

fread只有.PNG文件的前5个字节

我已经制作了一个简单的资源包装器,用于将我的游戏资源打包到一个文件中.在我开始编写解包器之前,一切都很顺利.我注意到我已经打包的.txt文件--26个字节 - 来自资源文件,没有任何问题,保留了所有数据.但是,当读取我在资源文件中打包的.PNG文件时,前5个字节完好无损,而其余的则完全无效.

我追溯到打包过程,我注意到fread只读取.PNG文件的前5个字节,我不能为我的生活找出原因.它甚至触发'EOF'表示文件只有5个字节长,而实际上它是一个787字节的小多边形PNG,100px×100px.

我甚至通过单独的应用程序来简单地将这个PNG文件读入缓冲区来测试这个问题,我得到相同的结果,只读取5个字节.

以下是该小型独立应用程序的代码:

#include <cstdio>

int main(int argc, char** argv)
{
    char buffer[1024] = { 0 };
    FILE* f = fopen("test.png", "r");
    fread(buffer, 1, sizeof(buffer), f);
    fclose(f);        //<- I use a breakpoint here to verify the buffer contents
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

有人可以指出我的愚蠢错误吗?

c file-io stdio msvcrt fread

9
推荐指数
2
解决办法
4205
查看次数

ftell在2GB以上的位置

在32位系统上,ftell如果以二进制模式打开的文件的当前位置指示符超过2GB点,会返回什么?在C99标准中,这是未定义的行为,因为ftell必须返回一个long int(最大值为2**31-1)?

c file-io stdio c99 ftell

9
推荐指数
2
解决办法
7636
查看次数

sprintf/snprintf是否分配了额外的内存?

我正在编写一个库,并希望使它绝对与资源无关,这也意味着库应该使用用户提供的内存分配功能.库允许用户也设置自己的错误处理函数,这些函数以错误消息作为参数调用,如下所示:

typedef void (*error_handler)(const char* msg);
Run Code Online (Sandbox Code Playgroud)

库代码自己准备错误消息,就像那样(消息格式化失败的情况):

char buf[BUF_SIZE];
snprintf(buf, BUF_SIZE, "Oops found at file '%s' line %d", __FILE__, __LINE__);
Run Code Online (Sandbox Code Playgroud)

但是我可以确定snprintf不会为malloc的内部使用分配更多内存,显然会绕过用户提供的分配例程吗?我的Linux系统中的手册页对此保持沉默.

c memory-management stdio

9
推荐指数
2
解决办法
7042
查看次数

使用读取模式打开的流的fputc()行为

我无法找到任何对使用fputc()时创建流的指定行为的引用fopen("/some/path", "r").

我搜索了C11草案n1570 pdf寻找没有运气的任何参考,fopen()功能规范谈到将未知字符作为模式参数传递,这是未定义的行为.但它没有说明创建的流上的后续IO.

这是fwrite()功能规范

7.21.8.2 fwrite功能

概要

  1. #include <stdio.h>
    size_t fwrite(const void * restrict ptr,
        size_t size, size_t nmemb, FILE * restrict stream);
    
    Run Code Online (Sandbox Code Playgroud)

描述

  1. fwrite函数写入,从阵列所指向的ptr,最多nmemb,其大小由指定的元素size,到流指向stream.对于每个对象,对fputc函数进行大小调用,从unsigned char完全覆盖对象的数组中获取值(按顺序).流的文件位置指示符(如果已定义)按成功写入的字符数提前.如果发生错误,则流的文件位置指示符的结果值是不确定的.

返回

  1. fwrite函数返回成功写入的元素数,这将少于nmemb仅在遇到写入错误时.如果为sizenmemb为零,则fwrite返回零,并且流的状态保持不变.

这需要我们的fputc()功能,所以

7.21.7.3 fputc功能

概要

  1. #include <stdio.h>
    int fputc(int c, FILE *stream);
    
    Run Code Online (Sandbox Code Playgroud)

描述

  1. fputc …

c fopen stdio undefined-behavior language-lawyer

9
推荐指数
1
解决办法
174
查看次数

创建新文件以避免竞争条件

我需要开发一个C++例程来执行这个显然是微不足道的任务:只有在文件不存在时才创建文件,否则什么也不做/引发错误.

由于我需要避免竞争条件,我想使用"请求宽恕不允许"原则(即尝试预期的操作并检查它是否成功,而不是提前检查前提条件),据我所知,这是唯一的用于此目的的强大且可移植的方法[维基百科文章] [getline的一个例子].

不过,在我的案例中,我无法找到实现它的方法.我能想到的最好的是打开一个fstreamin app模式(或者fopen"a"),用tellp(C++)或ftell(C)检查输出位置,如果这个位置不为零,则中止.然而,这有两个缺点,即如果文件存在则它被锁定(尽管很短的时间)并且其修改日期被改变.

我检查的其他可能的组合ios_base::openmodefstream,还有mode的字符串fopen,但没有发现这适合我的需求选择.进一步搜索C和C++标准库以及Boost Filesystem,证明是无用的.

有人能否指出一种方法以一种强有力的方式执行我的任务(没有附带效应,没有竞争条件)而不依赖于OS特定的功能?我的具体问题是在Windows中,但便携式解决方案将是首选.

编辑:BitWhistler的答案完全解决了C程序的问题.不过,我很惊讶没有C++惯用解决方案似乎存在.任何一个使用Andrew Henle提出openO_EXCL属性,但是特定于操作系统(在Windows中,属性似乎_O_EXCL用另外的下划线[MSDN]调用)或者单独编译C11文件并将其从C++代码链接.此外,获得的文件描述符不能转换为流,除非使用非标准扩展(例如GCC __gnu_cxx::stdio_filebuf).我希望未来的C++版本能够实现子"x"属性,也可能ios::实现文件流的相应修改器.

c c++ iostream stdio

9
推荐指数
1
解决办法
906
查看次数

为什么缓冲写入fmemopen()'ed FILE比无缓冲?

当然,磁盘上的文件缓冲I/O比无缓冲的速度快.但是为什么即使写入内存缓冲区也有好处?

以下基准代码示例使用gcc 5.40编译,使用优化选项-O3,与glibc 2.24链接.(请注意,常见的glibc 2.23有关于fmemopen()的错误.)

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

int main() {
  size_t bufsz=65536;
  char buf[bufsz];
  FILE *f;
  int r;

  f=fmemopen(buf,bufsz,"w");
  assert(f!=NULL);

  // setbuf(f,NULL);   // UNCOMMENT TO GET THE UNBUFFERED VERSION

  for(int j=0; j<1024; ++j) {
    for(uint32_t i=0; i<bufsz/sizeof(i); ++i) {
      r=fwrite(&i,sizeof(i),1,f);
      assert(r==1);
    }
    rewind(f);
  }

  r=fclose(f);
  assert(r==0);
}
Run Code Online (Sandbox Code Playgroud)

缓冲版本的结果:

$ gcc -O3 -I glibc-2.24/include/ -L glibc-2.24/lib  test-buffered.c 
$ time LD_LIBRARY_PATH=glibc-2.24/lib ./a.out
real    0m1.137s
user    0m1.132s
sys     0m0.000s
Run Code Online (Sandbox Code Playgroud)

无缓冲版本的结果

$ gcc -O3 -I glibc-2.24/include/ -L glibc-2.24/lib …
Run Code Online (Sandbox Code Playgroud)

c stdio

9
推荐指数
2
解决办法
660
查看次数

PyInstaller 无缓冲 stdio

问题

Docker 映像大小通常应尽可能小。使用像标准 python映像这样的成熟环境,在安装了所有依赖项的情况下,经常会导致严重臃肿的映像。将 python 打包成独立的可执行文件(例如使用 pyinstaller)是减少图像大小和整体复杂性的完美方式。

环境python3.6pyinstaller==3.4

出现的问题是,python 使用每个默认的缓冲 stdio。这可以通过使用python -u .... 但是在使用 pyinstaller 时变得无法访问。

根据文档,应该可以向生成的可执行文件添加运行时选项,例如u,vW ...。但不幸的是,实际上它似乎不起作用。两者,v并且W,正常工作,但u似乎被完全忽略。

以下代码段显示了用法:

...
exe = EXE(...
          [('u', None, 'OPTION')],
          name="myapp",
          ...)
...
Run Code Online (Sandbox Code Playgroud)

这个标志还有效吗?由于其他人工作 - 它是否在没有通知或更新文档的情况下被删除?

是否有替代方法可以禁用 stdio 缓冲(使用 pyinstaller 或外部),不像这样修改 python 代码?

为什么需要那个?

在运行 docker swarm 服务时,应避免缓冲 IO。为了使可执行文件正确地实时登录到 docker 守护进程,有必要附加一个 shell。但是将 tty shell 附加到 swarm 任务会使处理日志变得更加复杂,甚至是不可能的。

python stdio pyinstaller docker

9
推荐指数
1
解决办法
653
查看次数