在使用旧内容之前写入缓冲区

时间:2013-06-16 12:08:59

标签: c

使用memset()初始化缓冲区然后使用不同的调用来向其添加特定数据是有效的吗?

示例:

        DIR *dirp;
        struct dirent *dp;
        struct dirent *buf;

        dirp = opendir("/dev");
        if( dirp ) {
            buf = (struct dirent *)malloc(offsetof(struct dirent, d_name) + NAME_MAX + 1);
            if (buf == NULL) {
                closedir( dirp );
                return = ENOMEM;
            }
            while( readdir_r(dirp, buf, &dirp) == 0 && dirp ) {
                if( strncmp( dp->d_name, "video", 5 ) == 0 ) {
                    char vidpath[21];
                    memset( vidpath, 0x0, sizeof( vidpath ) );
                    snprintf( vidpath, 20, "/dev/%s", dp->d_name );

                    // Now do an operation that prints the buffer...

                }
            }
            free ( buf );
            closedir( dirp );
        }

此致

3 个答案:

答案 0 :(得分:1)

通过避免动态分配可以简化程序(struct dirent具有较小的固定大小:名称加上几个整数)vidbuf不需要长于PATH_MAX(但如果是内存)非常紧,你可以使用预先计算的值,比如20,并测试snprintf()的返回值)

#include <stdio.h>
#include <string.h>
#include <dirent.h>

void do_stuff(char * dev);
void do_stuff(char * dev)
{
DIR *dirp;
struct dirent entbuf, *dp;
char vidpath[ PATH_MAX ];

        dirp = opendir(dev);
        if (!dirp ) return;

        while ( !readdir_r(dirp, &entbuf, &dp) ) {
                if ( !dp ) break;
                if ( memcmp( dp->d_name, "video", strlen("video")  ) ) continue;
                snprintf( vidpath,sizeof vidpath, "%s/%s", dev, dp->d_name );

                    // Now do an operation that prints the buffer...
                fprintf(stderr, "Yes: %s\n", vidpath );

            }
        closedir( dirp );
}

int main(void)
{

do_stuff ( "/dev" );

return 0;
}

答案 1 :(得分:0)

memset将内存初始化为给定值,因此它是无效的,并且是确保没有不良副作用的良好做法。既然你正在使用snprintf,那么它并不是严格必要的,因为你传递的是size-1,所以memset在循环中不是必需的。

你也应该使用sizeof(vidpath)来获取snprintf。

 snprintf( vidpath, sizeof(vidpath), "/dev/%s", dp->d_name );

答案 2 :(得分:0)

首先请注意:

char vidpath[21];
memset( vidpath, 0x0, sizeof( vidpath ) );

可以写成:

char vidpath[21] = {0};

但当然以你的方式致电memset是有效的。

现在,当您正在调用snprintf时,首先无法初始化缓冲区。

而不是:

snprintf( vidpath, 20, "/dev/%s", dp->d_name );

你可以写

snprintf( vidpath, 21, "/dev/%s", dp->d_name );

或更好

snprintf( vidpath, sizeof vidpath, "/dev/%s", dp->d_name );

因为snprintf总是写空终止符(除非指定的最大大小为0)。