【问题标题】:Declared with attribute warn_unused_result [-Wunused-result]用属性 warn_unused_result [-Wunused-result] 声明
【发布时间】:2025-12-22 03:45:15
【问题描述】:

我使用 Ideone.com 编译了以下代码,并弹出以下警告。

rtctimer.c: In function 'rtctimer_next_tick':
rtctimer.c:87.7: warning: ignoring return value of 'read', 
                 declared with attribute warn_unused_result [-Wunused-result]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <sched.h>
#include <fcntl.h>
#include <math.h>
#include <sys/ioctl.h>
#include <linux/rtc.h>
#include "rtctimer.h"

struct rtctimer_s
{
    int rtc_fd;
    int current_hz;
    int rtc_running;
    int verbose;
    int usecs;
};

rtctimer_t *rtctimer_new( int verbose )
{
    rtctimer_t *rtctimer = malloc( sizeof( rtctimer_t ) );
    if( !rtctimer ) return 0;

    rtctimer->verbose = verbose;
    if( (( rtctimer->rtc_fd = open( "/dev/rtc", O_RDONLY ) ) < 0) ) {
        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: Cannot open /dev/rtc: %s\n",
                     strerror( errno ) );
        }
        if( ( rtctimer->rtc_fd = open( "/dev/misc/rtc", O_RDONLY ) ) < 0 ) {
            if( rtctimer->verbose ) {
                fprintf( stderr, "rtctimer: Cannot open /dev/misc/rtc: %s\n",
                         strerror( errno ) );
            }
            free( rtctimer );
            return 0;
        }
    }

    if( fcntl( rtctimer->rtc_fd, F_SETOWN, getpid() ) < 0 ) {
        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: Cannot set ownership of "
                             "/dev/rtc: %s\n", strerror( errno ) );
        }
        close( rtctimer->rtc_fd );
        free( rtctimer );
        return 0;
    }

    rtctimer->rtc_running = 0;
    rtctimer->current_hz = 0;
    rtctimer->usecs = 0;
    return rtctimer;
}

void rtctimer_delete( rtctimer_t *rtctimer )
{
    rtctimer_stop_clock( rtctimer );
    close( rtctimer->rtc_fd );
    free( rtctimer );
}

int rtctimer_next_tick( rtctimer_t *rtctimer )
{
    unsigned long rtc_data;
    struct pollfd pfd;
    pfd.fd = rtctimer->rtc_fd;
    pfd.events = POLLIN | POLLERR;

again:
    if( poll( &pfd, 1, 100000 ) < 0 ) {
        if( errno == EINTR ) {
            goto again;
        }

        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: poll call failed: %s\n",
                     strerror( errno ) );
        }
        return 0;
    }

    read( rtctimer->rtc_fd, &rtc_data, sizeof( rtc_data ) );
    return 1;
}

int rtctimer_set_interval( rtctimer_t *rtctimer, int hz )
{
    int restart;

    if( hz == rtctimer->current_hz ) {
        return 1;
    }

    restart = rtctimer_stop_clock( rtctimer );

    if( ioctl( rtctimer->rtc_fd, RTC_IRQP_SET, hz ) < 0 ) {
        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: Cannot set periodic interval: %s\n",
                     strerror( errno ) );
        }
        return 0;
    }

    rtctimer->current_hz = hz;
    rtctimer->usecs = (int) ( ( ( 1000.0 * 1000.0 ) / hz ) + 0.5 );

    if( restart ) {
        rtctimer_start_clock( rtctimer );
    }

    return 1;
}

int rtctimer_start_clock( rtctimer_t *rtctimer )
{
    if( !rtctimer->rtc_running ) {
        if( ioctl( rtctimer->rtc_fd, RTC_PIE_ON, 0 ) < 0 ) {
            if( rtctimer->verbose ) {
                fprintf( stderr, "rtctimer: Cannot start periodic "
                         "interrupts: %s\n", strerror( errno ) );
            }
            return 0;
        }
        rtctimer->rtc_running = 1;
    }
    return rtctimer->rtc_running;
}

int rtctimer_stop_clock( rtctimer_t *rtctimer )
{
    int was_running = rtctimer->rtc_running;

    if( rtctimer->rtc_running ) {
        if( ioctl( rtctimer->rtc_fd, RTC_PIE_OFF, 0 ) < 0 ) {
            if( rtctimer->verbose ) {
                fprintf( stderr, "rtctimer: Cannot stop periodic "
                         "interrupts: %s\n", strerror( errno ) );
            }
            return rtctimer->rtc_running;
        }
        rtctimer->rtc_running = 0;
    }

    return was_running;
}

int rtctimer_get_resolution( rtctimer_t *rtctimer )
{
    return rtctimer->current_hz;
}

int rtctimer_get_usecs( rtctimer_t *rtctimer )
{
    return rtctimer->usecs;
}

int set_realtime_priority( int max )
{
    struct sched_param schp;

    memset( &schp, 0, sizeof( schp ) );
    if( max ) schp.sched_priority = sched_get_priority_max( SCHED_FIFO );
    else schp.sched_priority = sched_get_priority_max( SCHED_FIFO ) - 1;

    if( sched_setscheduler( 0, SCHED_FIFO, &schp ) != 0 ) {
        return 0;
    }

    return 1;
}

int set_default_priority( void )
{
    struct sched_param schp;

    memset( &schp, 0, sizeof( schp ) );
    schp.sched_priority = 0;
    if( sched_setscheduler( 0, SCHED_OTHER, &schp ) != 0 ) {
        return 0;
    }

    return 1;
}

我做错了什么?

【问题讨论】:

    标签: c


    【解决方案1】:

    read() 返回一个值,指示它读取的字节数。警告表明代码忽略了这一点。您应该检查read() 的返回值以确保它成功,否则您会假设rtc_data 已正确填充,但可能没有正确填充。

    【讨论】:

      【解决方案2】:

      您没有检查read 的返回值,这是一个等待发生的错误。

      ssize_t r = read(rtctimer->rtc_fd, &rtc_data, sizeof( rtc_data ) );
      if (r == -1) {
         // deal with failed read
      } else if (r != sizeof(rtc_data)) {
         // you didn't read as much as you wanted to
      ...
      

      如果您不检查读取返回的内容,那么如果确实发生读取错误,您的程序很可能会意外失败,并且无法调试。 (第二种情况可能不适用于此特定示例,或者对于某些管道读取。)

      始终检查库调用的返回值,尤其是 I/O 调用,因为它们在正常情况下确实会失败。

      【讨论】:

        【解决方案3】:

        线

          read( rtctimer->rtc_fd, &rtc_data, sizeof( rtc_data ) );
        

        产生一个结果(read() 的返回值),你不要以任何方式使用它,这会给你一个警告。这就是-Wunused-result的目的。

        忽略 read() 的返回值通常是一个非常糟糕的主意!

        【讨论】: