如何在保存函数返回值时打印errno?

4

我使用open()函数无法正确地打开/创建文件,所以我想使用errno消息来帮助我找出原因。然而,我不知道如何设置if()语句,以便它打印出错误信息。 我知道像这样的代码应该可以工作:

if(open(handle,O_RDWR | O_CREAT) == -1){
      printf("%s\n",strerror(errno));
}

但是如果我想将open()的值保存到我的变量中,如果它是-1,则也打印错误怎么办?我不想为此调用两次open(),也不知道如何在它是ok的情况下进行分配,以及如何在不ok的情况下打印错误。

 #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    #include <errno.h>


    int main(int argc, char **argv){
        int handle,i,help;
        int *array = malloc(5*sizeof(int));
        float *red = malloc(5*sizeof(int));

        array[0]=5;
        array[1]=4;
        array[2]=3;
        array[3]=2;
        array[4]=1;

        handle = open(argv[1], O_RDWR | O_CREAT);
        if(handle == -1){
            printf("%s\n",strerror(errno));
        }

        printf("handle 1 %d\n",handle);
        write(handle,array,20);
        close(handle);

        handle = open(argv[1], O_RDONLY);
        lseek(handle,0,SEEK_SET);
        printf("handle %d\n",handle);
        help=read(handle,&red,20);
        printf("pomoc %d\n",help);
        for(i=0; i<5; i++){
            printf("%d\n",(int)red[i]);
        }
        close(handle);
        return 0;
    }

这是我的“尝试”代码,因为我不确定read()函数如何工作,所以我想尝试一下是否可以将任何类型的指针传递进去并读取任意数量的字节,看看是否能够正常工作,但我甚至无法通过开头部分。 - ligazetom
请注意,在报告错误后,不应继续打开句柄。错误应在标准错误流上报告,而不是标准输出。 - Jonathan Leffler
3个回答

3
问题不在于变量的赋值,而在于您调用open的方式:
handle = open(argv[1], O_RDWR|O_CREAT); // wrong number of arguments
if (handle == -1) {
    printf("%s\n",strerror(errno));
}

当您使用O_CREAT时,必须给open三个参数。如果没有,则行为未定义。偶尔,当您在if内调用open时,会返回-1的错误值,而将其赋值给变量时则返回非负值。
除非您有充分理由这样做,否则open的第三个参数应该是神奇数字0666。(唯一的充分理由是创建一个文件,用于保存秘密信息; 然后使用0600。)(前导零是必需的。)虽然有可以用于open第三个参数的符号常量,但是一旦了解了数字“模式”意味着什么,符号常量实际上更难读取。这里详细解释了符号和数字形式的“模式”。

顺便提一下,当系统调用失败时,您应该始终打印两者 strerror(errno)有问题的文件的名称(如果有):

handle = open(argv[1], O_RDWR|O_CREAT, 0666);
if (handle == -1) {
    printf("%s: %s\n", argv[1], strerror(errno));
    exit(1);
}

您需要考虑是否应该使用O_EXCLO_TRUNC


1
或者考虑使用 O_TRUNC,如果不使用 O_EXCL - Jonathan Leffler

1
正确的做法是:

这样做:

    if((handle=open(argv[1], O_RDWR|O_CREAT, 0666)) == -1){

请注意,对于 O_CREAT,需要提供 pmode 参数。

那么什么是这些模式呢?我看过更多的对话,但迄今为止我还没有看到关于它的任何教程。顺便说一下,我正在使用Linux。 - ligazetom
_S_IREAD_S_IWRITE是非标准的。open函数的第三个参数几乎总是应该为0666;最重要的例外是包含_机密信息_的文件,对于这种情况应该使用0600 - zwol

0

看起来你做得很对;只需将open()的返回值保存到变量中,然后将其与-1进行比较。很好。

请注意,这是错误的:

float *red = malloc(5*sizeof(int));

因为不能保证 floatint 的大小相同,所以这种写法是错误的且非常令人困惑。最好不要在 malloc() 中重复类型,因为这样会引入错误。而应该这么写:

float * const red = malloc(5 * sizeof *red);

这里使用 sizeof *red 来计算 sizeof (float),同时确保类型是程序中实际指针的类型。还要注意使用 const 来防止后续重新分配 red,从而避免可能导致内存泄漏的情况。


我不确定,因为以这种方式操作时,句柄突然变成了0而不是-1,它似乎不知道要打印什么。关于分配,我知道它不能正常使用,但我只是尝试使用低级函数能做些什么,既然你指出了,那我能问一下应该怎么做吗?我必须写一个无符号字符的字节,然后是随机数量的浮点数,全部都是二进制。应该如何将它们读回内存中? - ligazetom
@ligazetom 这是一个完全不同的问题,涉及到如何编码/序列化数据,通过在评论中回答这个问题违反了该网站的工作原则。请发布相关的问题或进行搜索,我知道这已经出现了很多次。 - unwind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接