C-在memcpy()之后从函数返回时出现段错误

我具有以下代码,用于读写使用FUSE实现的文件系统。该文件已映射到内存区域,我需要从文件系统中的内存读取到缓冲区。但是,即使read函数到达了return语句,在返回给调用者之前也会发生段错误。写入功能非常相似,并且可以正常工作。

我的读写功能如下所示:

// Write
int as3fs_write( filesystem *fs, char *path, void *buffer, size_t length ) {

// TODO check if file is open?
printf( "write - length to write: %ld\n", length );

// Find entry
entry *e = locate_entry( fs, path );
if ( e == NULL ) {
    return -1; // NOT FOUND
}

node *n = (node*) getPointer( fs, e->data );

int wp = 0; // Write pointer

data_record *record;
data_record *new_record;
offset new_record_offset;

record = (data_record*) getPointer( fs, n->data_last );

// In case there are no records, make one
if ( record == NULL ) {

    printf( "write - Creating new first record for this file\n" );

    n->data_first = find_hole( fs, sizeof( data_record ) );
    n->data_last = n->data_first;

    data_record *new_record = getPointer( fs, n->data_first );
        new_record->next = OFFSET_NULL;
        new_record->length = 0;

    record = new_record;
}

// Main loop, write data
while( wp < length ) {

    // Write to record
    size_t space_in_record = RECORD_SIZE - record->length;
    size_t want_to_write = length - wp;

    printf( "write - New record - wants to write %ld bytes, space in record for %ld bytes.\n", want_to_write, space_in_record );

    // Check if the data fits in this record
    if ( want_to_write <= space_in_record ) {

        // Space for all data, write and exit

        printf( "write - All remaining writeable data fit in this record.\n" );

        memcpy( record->data + record->length, buffer + wp, want_to_write );
        record->length += want_to_write;

        // We are done, break out of while loop
        wp += want_to_write;
        break;

    } else {
        // Not space for all data, write available data and create new data record

        printf( "write - Writing partially.\n" );

        // First, write the data that we can write
        memcpy( record->data + record->length, buffer + wp, space_in_record );
        record->length += space_in_record;

        // Create new record and restart loop and write the rest of the data
        new_record_offset = find_hole( fs, sizeof( data_record ) );
        new_record = (data_record*) getPointer( fs, new_record_offset );
            new_record->length = 0;
            new_record->next = OFFSET_NULL;

        // Link in linked list
        record->next = new_record_offset;
        n->data_last = new_record_offset;

        wp += space_in_record;
    }
}

// Done writing data
e->size += length;

return wp;
}



// Read, return number of bytes read
int as3fs_read( filesystem *fs, char *path, void *buffer, size_t length ) {

printf( "read - started to read\n" );

// Find entry
entry *e = locate_entry( fs, path );

if ( e == NULL ) {
    return -1; // NOT FOUND
}

printf( "Entry %s located\n", e->name );

node *n = (node*) getPointer( fs, e->data );

printf( "Node located\n" );

data_record *record = (data_record*) getPointer( fs, n->data_first );

printf( "Record found\n" );



int rp = 0; // Read pointer in buffer, represents number of bytes read
int want_to_read, data_available;

while( rp < length ) {

    want_to_read = length - rp;
    data_available = record->length;

    // Check relation of bytes left to read and available bytes in record
    if ( want_to_read <= data_available ) {
        // We can read all the rest of the data from record

        printf( "read - Able to read all data from this record. %d bytes. Current rp = %d. Buffer address: %x.\nWriting to address %x\n", want_to_read, rp, buffer, buffer + rp );

        memcpy( buffer + rp, record->data, want_to_read );
        rp += want_to_read;

        printf( "buffer: %s\n", (char*) buffer );

        break;

    } else {
        // Want to read more than what is in the record. Read this record and continue to next.

        printf( "Reading partially\n" );

        // Copy current record
        memcpy( buffer+rp, record->data, data_available );
        rp += data_available;

        // Debug print memcpy data
        printf( "buffer: %s\n", (char*) buffer );

        if ( record->next == OFFSET_NULL ) {
            // There is no more data after this, done reading
            break;
        }

        // Reference the next record
        record = (data_record*) getPointer( fs, record->next );
    }
}

printf( "read - Success, rp = %d\n", rp );
return rp;
}

我制作了一个快速测试程序来测试功能:

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <sys/mman.h>

#include "as3fs.h"



int main( int argc, const char* argv[] ) {

// Initialise filesystem
filesystem *fs = as3fs_init( "test_disk.img" );

// Traverse and print
traverse( fs, fs->root, print_entry );

hole_print( fs );

printf( "\n\nR/W TEST\n\n" );

char *writebuffer = malloc( 8000 * sizeof( char ));
char *readbuffer = malloc( 8000 * sizeof( char ) );
int res_write;
int res_read;

printf( "Allocated write buffer at %x, read buffer at %x\n", writebuffer, readbuffer );

strcpy( writebuffer, "din mor." );
res_write = as3fs_write( fs, "/testdir/fileintestdir", writebuffer, strlen( "abcdefgh") + 1 );

printf( "Write return code %d\n", res_write );

res_read = as3fs_read( fs, "/testdir/fileintestdir", readbuffer, strlen( "abcdefgh") + 1 );

printf( "returned from read\n" );
printf( "Read return code: %d\n", res_read );
//printf( "%s\n", readbuffer );

return 0;
}

我已经复制粘贴了测试程序输出的相关部分。其中一些行是从其他功能打印的:

R/W TEST

Allocated write buffer at b4471870, read buffer at b44737c0
write - length to write: 9
current_dir at start: 
locate - Locate started, looking for directory /testdir
locate - first token is: testdir
locate - new string is testdir
locate - scanning entry testdir
locate - entering subdirectory testdir
locate - Finished successfully
write - Creating new first record for this file
Finding holes
Found hole at 4304, size = 77616
write - New record - wants to write 9 bytes, space in record for 4080 bytes.
write - All remaining writeable data fit in this record.
Write return code 9
read - started to read
current_dir at start: 
locate - Locate started, looking for directory /testdir
locate - first token is: testdir
locate - new string is testdir
locate - scanning entry testdir
locate - entering subdirectory testdir
locate - Finished successfully
Entry fileintestdir located
Node located
Record found
read - Able to read all data from this record. 9 bytes. Current rp = 0. Buffer address: b44737c0.
Writing to address b44737c0
buffer: abcdefg
read - Success, rp = 9
[1]    23122 segmentation fault  sudo ./as3fs_test_rw

我无法弄清楚怎么可能到达read函数的末尾,正如在测试程序中的下一条语句之前进行段错误时,通过“ read-success,rp = 9”行所确认的那样。