【发布时间】:2014-09-24 02:55:02
【问题描述】:
我有一个看起来像这样的 for 循环:
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 是一个类型定义的结构,它只是一个标准的struct statfs,添加了三个字段。对函数merge_statfs_structs() 的调用使用tmp 指向的标准结构中的值填充f_tmp 指向的扩展结构。对strcpy() 的三个调用填充了额外的三个字段。
代码编译正常,但我可以从一些 printf 调用中看到程序在调用 free() 时出现段错误。早些时候,我在循环外进行了声明和 malloc 调用,并尝试将两个结构都重置为 NULL,但这是在第二次调用 merge_statfs_structs 时出现段错误。
所以我想我的问题是如何在每次循环中“重置” f_tmp 和 tmp 指向的结构?
编辑:添加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;
}
编辑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 是 for 循环中 fse[i2] 引用的结构。如果你想看一下,我在 github here 上有整个文件。
我在 gdb 中一直在玩这个,段错误发生在 glibc 内部,在调用 free 期间。不幸的是,我的 glibc 不是用调试符号构建的,所以我不能使用 valgrind 来追踪它。
【问题讨论】:
-
可能您在新字段中写得越界,
strcpy复制直到找到\0。您确定原始字段以\0结尾吗?有时有固定大小,例如char field[16];。 -
不,我仔细检查了,甚至将
strcpy更改为strncpy并完全匹配源/目标大小。我能够很好地打印这些值。通过 gdb 'backtrace' 运行它并得到:1 0x0000000000401303 in getfsstat_linux (buf=0x7fffffffdf90, bufsize=453452) at src/mount.h:165第 165 行是对 free() 的第一次调用。 -
您可能想展示如何定义
struct statfs_full和struct statfs。 -
已经这样做了,谢谢。
-
请编译所有警告和调试信息 (
gcc -Wall -g) 并使用调试器 (gdb)
标签: c pointers memory-management struct