声明属性warn_unused_result [-Wunused-result]

时间:2012-02-05 09:10:30

标签: c

我使用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;
}

我做错了什么?

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

你没有检查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,因为它们在正常情况下会失败。

答案 2 :(得分:1)

该行

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

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

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