我试图从一个二进制文件中读取数据到一个inode结构中。为了表示一个文件系统。但是我得到了一个分段错误,并且不知道如何修复它。我已经在load_inodes函数和debug_fs函数中打印了地址。我的问题是,如何更改load_inodes,以使其余代码正常工作?我猜我必须使用malloc将数据添加到堆中以使其正确。或者可能条目有问题,因此子输出的地址为0x1
二进制文件如下所示:
00000000: 0000 0000 0200 0000 2f00 0100 0000 0000 ......../.......
00000010: 0200 0000 0100 0000 0000 0000 0200 0000 ................
00000020: 0000 0000 0100 0000 0700 0000 6b65 726e ............kern
00000030: 656c 0000 0120 4e00 0005 0000 0000 0000 el... N.........
00000040: 0000 0000 0001 0000 0000 0000 0002 0000 ................
00000050: 0000 0000 0003 0000 0000 0000 0004 0000 ................
00000060: 0000 0000 0002 0000 0004 0000 0065 7463 .............etc
00000070: 0001 0000 0000 0001 0000 0003 0000 0000 ................
00000080: 0000 0003 0000 0006 0000 0068 6f73 7473 ...........hosts
00000090: 0000 01c8 0000 0001 0000 0005 0000 0000 ................
000000a0: 0000 00
前四个字节是它的id。接下来的四个是名称的长度。接下来的字节是名称。接下来的两个字节是is_directory和is_readonly。接下来的四个是filesize。接下来的四个是entries。
inode.c的相关部分如下所示:
struct inode* load_inodes() /* this one works on the first inode loadexample1 */
{
printf("Start of load_inodes()");
FILE* f = fopen("master_file_table", "rb");
if (f == NULL) {
fprintf(stderr, "Failed to open master_file_table for reading\n");
perror("reason:");
return NULL;
}
printf("NUM_INODES * sizeof: %ld\n\n", NUM_INODES * sizeof(struct inode));
// Allocate memory for inodes array
struct inode* inodes = (struct inode*) malloc(NUM_INODES * sizeof(struct inode)+100000);
printf("ja\n");
if (inodes == NULL) {
fprintf(stderr, "Failed to allocate memory for inodes\n");
fclose(f);
return NULL;
}
printf("Before mainloop\n");
// Read each inode from the file and store it in the inodes array
for (int i = 0; i < NUM_INODES; i++) {
uint32_t id;
fread(&id, sizeof(uint32_t), 1, f);
inodes[i].id = id;
printf("ID: %d\n", id);
uint32_t name_len;
fread(&name_len, sizeof(uint32_t), 1, f);
printf("Namelength: %d\n", name_len);
char* name = (char*) malloc(name_len + 1);
if (name == NULL) {
fprintf(stderr, "Failed to allocate memory for inode name\n");
fclose(f);
free(inodes);
return NULL;
}
fread(name, sizeof(char), name_len, f);
name[name_len] = '\0';
inodes[i].name = name;
printf("Name: %s\n", name);
char is_directory;
fread(&is_directory, sizeof(char), 1, f);
inodes[i].is_directory = is_directory;
printf("Is_directory: %d\n", is_directory);
char is_readonly;
fread(&is_readonly, sizeof(char), 1, f);
inodes[i].is_readonly = is_readonly;
printf("Is_readonly: %d\n", is_readonly);
uint32_t filesize;
fread(&filesize, sizeof(uint32_t), 1, f);
inodes[i].filesize = filesize;
printf("Filesize: %d\n", filesize);
uint32_t num_entries;
fread(&num_entries, sizeof(uint32_t), 1, f);
inodes[i].num_entries = num_entries;
printf("Num_entries: %d\n", num_entries);
if (num_entries > 0) {
uintptr_t* entries = (uintptr_t*) malloc(num_entries * sizeof(uintptr_t));
if (entries == NULL) {
fprintf(stderr, "Failed to allocate memory for inode entries\n");
fclose(f);
free(inodes);
return NULL;
}
fread(entries, sizeof(uintptr_t), num_entries, f);
inodes[i].entries = entries;
printf("Entries: %d\n\n", *entries);
} else {
inodes[i].entries = NULL;
}
}
printf("Address: %p Name: %s\n", inodes[0], inodes[0].name);
printf("Address: %p Name: %s\n", inodes[1], inodes[1].name);
printf("Address: %p Name: %s\n", inodes[2], inodes[2].name);
printf("Address: %p Name: %s\n", inodes[3], inodes[3].name);
// printf("%d\n", inodes[0].is_directory);
fclose(f);
// inode_ptr = malloc(10000)
return inodes;
}
void fs_shutdown( struct inode* inode )
{
}
/* This static variable is used to change the indentation while debug_fs
* is walking through the tree of inodes and prints information.
*/
static int indent = 0;
void debug_fs( struct inode* node )
{
printf("Name: %s Address: %p\n", node->name, &node);
if( node == NULL ) return;
for( int i=0; i<indent; i++ )
printf(" ");
if( node->is_directory )
{
printf("%s (id %d) (address: %p\n", node->name, node->id, node);
indent++;
for( int i=0; i<node->num_entries; i++ )
{
struct inode* child = (struct inode*)node->entries[i];
printf("Child: %p\n", child);
debug_fs( child );
}
indent--;
}
else
{
printf("%s (id %d size %db blocks ", node->name, node->id, node->filesize );
for( int i=0; i<node->num_entries; i++ )
{
printf("%d ", (int)node->entries[i]);
}
printf(")\n");
}
}
load_fs. c的相关部分如下所示:
int main()
{
printf("===================================\n");
printf("= Load all inodes from the file =\n");
printf("= master_file_table =\n");
printf("===================================\n");
struct inode* root = load_inodes();
debug_fs( root );
debug_disk();
使用valgrind运行load_fs后的输出:
===================================
= Load all inodes from the file =
= master_file_table =
===================================
Start of load_inodes()NUM_INODES * sizeof: 160
ja
Before mainloop
ID: 0
Namelength: 2
Name: /
Is_directory: 1
Is_readonly: 0
Filesize: 0
Num_entries: 2
Entries: 1
ID: 1
Namelength: 7
Name: kernel
Is_directory: 0
Is_readonly: 1
Filesize: 20000
Num_entries: 5
Entries: 0
ID: 2
Namelength: 4
Name: etc
Is_directory: 1
Is_readonly: 0
Filesize: 0
Num_entries: 1
Entries: 3
ID: 3
Namelength: 6
Name: hosts
Is_directory: 0
Is_readonly: 1
Filesize: 200
Num_entries: 1
Entries: 5
Address: 0x55a9e70 Name: /
Address: 0x55a9f10 Name: kernel
Address: 0x55a9fd0 Name: etc
Address: 0x55aa070 Name: hosts
Name: / Address: 0x1ffefff5c8
/ (id 0) (address: 0x558f6b0
Child: 0x1
==3689174== Invalid read of size 8
==3689174== at 0x4017E3: debug_fs (inode.c:298)
==3689174== by 0x4018BA: debug_fs (inode.c:311)
==3689174== by 0x40199D: main (load_fs.c:13)
==3689174== Address 0x9 is not stack'd, malloc'd or (recently) free'd
==3689174==
==3689174==
==3689174== Process terminating with default action of signal 11 (SIGSEGV)
==3689174== Access not within mapped region at address 0x9
==3689174== at 0x4017E3: debug_fs (inode.c:298)
==3689174== by 0x4018BA: debug_fs (inode.c:311)
==3689174== by 0x40199D: main (load_fs.c:13)
==3689174== If you believe this happened as a result of a stack
==3689174== overflow in your program's main thread (unlikely but
==3689174== possible), you can try to increase the size of the
==3689174== main thread stack using the --main-stacksize= flag.
==3689174== The main thread stack size used in this run was 8388608.
==3689174==
==3689174== HEAP SUMMARY:
==3689174== in use at exit: 101,279 bytes in 10 blocks
==3689174== total heap usage: 12 allocs, 2 frees, 109,959 bytes allocated
==3689174==
==3689174== 23 bytes in 4 blocks are still reachable in loss record 1 of 4
==3689174== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==3689174== by 0x4013B9: load_inodes (inode.c:163)
==3689174== by 0x40198D: main (load_fs.c:12)
==3689174==
==3689174== 72 bytes in 4 blocks are still reachable in loss record 2 of 4
==3689174== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==3689174== by 0x4015ED: load_inodes (inode.c:197)
==3689174== by 0x40198D: main (load_fs.c:12)
==3689174==
==3689174== 1,024 bytes in 1 blocks are still reachable in loss record 3 of 4
==3689174== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==3689174== by 0x52500FF: _IO_file_doallocate (in /usr/lib64/libc-2.28.so)
==3689174== by 0x525E06F: _IO_doallocbuf (in /usr/lib64/libc-2.28.so)
==3689174== by 0x525D2D7: _IO_file_overflow@@GLIBC_2.2.5 (in /usr/lib64/libc-2.28.so)
==3689174== by 0x525C47E: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.28.so)
==3689174== by 0x5252542: puts (in /usr/lib64/libc-2.28.so)
==3689174== by 0x401965: main (load_fs.c:8)
==3689174==
==3689174== 100,160 bytes in 1 blocks are still reachable in loss record 4 of 4
==3689174== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==3689174== by 0x4012C3: load_inodes (inode.c:141)
==3689174== by 0x40198D: main (load_fs.c:12)
==3689174==
==3689174== LEAK SUMMARY:
==3689174== definitely lost: 0 bytes in 0 blocks
==3689174== indirectly lost: 0 bytes in 0 blocks
==3689174== possibly lost: 0 bytes in 0 blocks
==3689174== still reachable: 101,279 bytes in 10 blocks
==3689174== suppressed: 0 bytes in 0 blocks
==3689174==
==3689174== For lists of detected and suppressed errors, rerun with: -s
==3689174== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
make: *** [makefile:51: valgrind_load1] Segmentation fault (core dumped)
1条答案
按热度按时间t30tvxxf1#
它为我在递归调用
debug_fs()
时用child == 0x01
来分段错误。这对应于地址00000022
处的值。在
load_entries()
中,你用fread(entries, sizeof(uintptr_t), num_entries, f);
读取uintptr_t
值的数组,但在debug_fs()
中,你希望条目是struct
inode *`的数组。你可能希望这些条目是node的索引:在此更改之后,您的代码不再segfaults:
还有几个建议
1.写一个
free_inodes()
,如果malloc()
在load_indoes()
中失败,则使用它。这意味着你要确保数组中当前位置之后的所有i-〉name和i-〉条目都是NULL。最简单的方法是使用calloc()
而不是malloc()
:1.您可能希望更改
load_entries()
的接口,以便它可以告诉您文件中有多少个inode(而不是硬编码NUM_INODES
)。