2014-09-24 3 views
0

У меня есть цикл, который выглядит так:Как перебирает указатели на структуры

for (i2 = 0; i2 < n_lines; i2++) { 
    statfs_full *f_tmp; 
    f_tmp = malloc(sizeof(statfs_full)); 
    struct statfs *tmp; 
    tmp = malloc(sizeof(statfs)); 

    statfs(fse[i2].fs_file, tmp); 

    merge_statfs_structs(tmp, &f_tmp); 
    strcpy(f_tmp->f_fstypename, fse[i2].fs_vsftype); 
    strcpy(f_tmp->f_mntonname, fse[i2].fs_file); 
    strcpy(f_tmp->f_mntfromname, fse[i2].fs_spec); 

    free(f_tmp); 
    free(tmp); 

Он является частью более крупной функции. statfs_full - это структура typdef'ed, которая является стандартом struct statfs с тремя добавленными полями. Вызов функции merge_statfs_structs() заполняет мою развернутую структуру, на которую указывает f_tmp со значениями стандартной структуры, на которые указывает tmp. Три обращения к strcpy() заполняют дополнительные три поля.

Код компилируется ОК, но я вижу, как некоторые вызовы printf прерывают вызов при вызове (-ях) до free(). Раньше у меня были объявления и вызовы malloc за пределами цикла, и я попытался сбросить обе структуры до NULL, но это не соответствует второму вызову merge_statfs_structs.

Так что, я думаю, мой вопрос в том, как «сбросить» структуры, на которые указывают f_tmp и tmp за каждый раз через цикл?

Edit: Добавление источника merge_statfs_structs в случае это релевантно ...

int merge_statfs_structs(struct statfs *buf, statfs_full **buf_full) { 
    int i; 
    (*buf_full)->f_type = buf->f_type; 
    (*buf_full)->f_bsize = buf->f_bsize; 
    (*buf_full)->f_blocks = buf->f_blocks; 
    (*buf_full)->f_bfree = buf->f_bfree; 
    (*buf_full)->f_bavail = buf->f_bavail; 
    (*buf_full)->f_files = buf->f_files; 
    (*buf_full)->f_ffree = buf->f_ffree; 
    (*buf_full)->f_fsid = buf->f_fsid; 
    (*buf_full)->f_namelen = buf->f_namelen; 
    (*buf_full)->f_frsize = buf->f_frsize; 

    for (i = 0; i < 5; i++) 
     (*buf_full)->f_spare[i] = buf->f_spare[i]; 
    return 0; 
} 

Edit 2: добавление определение mounted_fs_entry и struct statfs_full:

#define FS_TYPE_LEN  90 
#define MNT_FLAGS_LEN 256 

typedef struct _mounted_fs_entry { 
    char fs_spec[PATH_MAX];   /* device or special file system path */ 
    char fs_file[PATH_MAX];   /* mount point */ 
    char fs_vsftype[FS_TYPE_LEN];  /* file system type */ 
    char fs_mntops[MNT_FLAGS_LEN]; /* mount flags */ 
    int fs_freq;      /* dump */ 
    int fs_passno;     /* pass */ 
} mounted_fs_entry; 

#if __WORDSIZE == 32 
#define __WORD_TYPE int 
#else /* __WORDSIZE == 64 */ 
#define __WORD_TYPE long int 
#endif 

typedef struct _statfs_full { 
    __WORD_TYPE f_type;    /* type of filesystem */ 
    __WORD_TYPE f_bsize;   /* optimal transfer block size */ 
    fsblkcnt_t f_blocks;   /* total data blocks in filesystem */ 
    fsblkcnt_t f_bfree;   /* free blocks in fs */ 
    fsblkcnt_t f_bavail;   /* free blocks available to unprivileged user */ 
    fsfilcnt_t f_files;   /* total file nodes in filesystem */ 
    fsfilcnt_t f_ffree;   /* free file nodes in fs */ 
    fsid_t  f_fsid;    /* filesystem id */ 
    __WORD_TYPE f_namelen;   /* maximum length of filenames */ 
    __WORD_TYPE f_frsize;   /* fragment size (since Linux 2.6) */ 
    __WORD_TYPE f_spare[5]; 

    /* these extra fields add path info as in the *BSD versions of statfs() */ 
    char f_fstypename[FS_TYPE_LEN]; /* fs type name */ 
    char f_mntonname[PATH_MAX];  /* directory on which mounted */ 
    char f_mntfromname[PATH_MAX]; /* mounted file sytem */ 
} statfs_full; 

Я не определил struct stafs себя, это определяется в /usr/include/sys/statfs.h, или вы можете просто man statfs. mounted_fs_entry - это структура, на которую ссылается fse[i2] в цикле for. У меня есть весь файл на github here, если вы хотите посмотреть.

Я играл с этим немного больше в gdb, segfault происходит внутри glibc, во время звонка на бесплатный. К сожалению, мой glibc не построен с отладочными символами, поэтому я не могу использовать valgrind для его отслеживания.

+0

вероятно, вы пишете из связанных в новых областях, 'strcpy' копирования до' \ 0'. Вы уверены, что поле origin закончилось с '\ 0'? несколько раз имеют фиксированный размер, например 'char field [16];'. – NetVipeC

+0

Нет, я дважды проверял, даже изменил 'strcpy' на' strncpy' и точно соответствовал исходным/целевым размерам. Я могу печатать значения в порядке. Побежал через GDB 'трассировку' и получил это: '1 0x0000000000401303 в getfsstat_linux (ЬиЕ = 0x7fffffffdf90, BUFSIZE = 453452) в ЦСИ/mount.h: 165' Line 165 является первым вызов бесплатно(). –

+0

Возможно, вам захочется показать, как определяются 'struct statfs_full' и' struct statfs'. – alk

ответ

0

Подумал сам. Перемещает malloc/free calls за пределы цикла и избавляется от операторов typedef при определении структур. Сейчас работает хорошо. Здесь никогда обновленный код (без проверки ошибок удалены):

struct statfs_ext *sas = malloc(sizeof(struct statfs_ext) * n_lines); 

struct statfs_ext *f_tmp; 
f_tmp = malloc(sizeof(struct statfs_ext)); 
if (f_tmp == NULL) { 
    perror("unable to malloc"); 
    exit(EXIT_FAILURE); 
} 

struct statfs *s_tmp; 
s_tmp = malloc(sizeof(struct statfs)); 
if (s_tmp == NULL) { 
    perror("unable to malloc"); 
    exit(EXIT_FAILURE); 
} 

for (i2 = 0; i2 < n_lines; i2++) { 

    if (statfs(fse[i2].fs_file, s_tmp) != 0) { 
     perror("statfs() failed"); 
     continue; /* might not be fatal */ 
    } 
    merge_statfs_structs(s_tmp, &f_tmp); 

    strncpy(f_tmp->f_fstypename, fse[i2].fs_vsftype, FS_TYPE_LEN);  
    strncpy(f_tmp->f_mntonname, fse[i2].fs_file, PATH_MAX); 
    strncpy(f_tmp->f_mntfromname, fse[i2].fs_spec, PATH_MAX); 

    sas[i2] = *f_tmp; 

} 

free(s_tmp); 
free(f_tmp); 

И stuct определения:

#define FS_TYPE_LEN  90 
#define MNT_FLAGS_LEN 256 

struct mounted_fs_entry { 
    char fs_spec[PATH_MAX];   /* device or special file system path */ 
    char fs_file[PATH_MAX];   /* mount point */ 
    char fs_vsftype[FS_TYPE_LEN];  /* file system type */ 
    char fs_mntops[MNT_FLAGS_LEN]; /* mount flags */ 
    int fs_freq;      /* dump */ 
    int fs_passno;     /* pass */ 
}; 

#if __WORDSIZE == 32 
#define __WORD_TYPE int 
#else /* __WORDSIZE == 64 */ 
#define __WORD_TYPE long int 
#endif 

struct statfs_ext { 
    __WORD_TYPE f_type;    /* type of filesystem (see below) */ 
    __WORD_TYPE f_bsize;   /* optimal transfer block size */ 
    fsblkcnt_t f_blocks;   /* total data blocks in filesystem */ 
    fsblkcnt_t f_bfree;   /* free blocks in fs */ 
    fsblkcnt_t f_bavail;   /* free blocks available to unprivileged user */ 
    fsfilcnt_t f_files;   /* total file nodes in filesystem */ 
    fsfilcnt_t f_ffree;   /* free file nodes in fs */ 
    fsid_t  f_fsid;    /* filesystem id */ 
    __WORD_TYPE f_namelen;   /* maximum length of filenames */ 
    __WORD_TYPE f_frsize;   /* fragment size (since Linux 2.6) */ 
    __WORD_TYPE f_spare[5]; 

    /* these extra fields add path info as in the *BSD versions of statfs() */ 
    char f_fstypename[FS_TYPE_LEN]; /* fs type name */ 
    char f_mntonname[PATH_MAX];  /* directory on which mounted */ 
    char f_mntfromname[PATH_MAX]; /* mounted file sytem */ 
}; 
Смежные вопросы