0

在我的createFileAddRecordAndRead()函数中,我创建了一个FixedLengthRecordFile对象的实例(它处理文件 I/O),然后使用它向文件中写入一条记录,然后再次读取它。

    FixedLengthRecordFile file;

   // The following opens the file in "wb+" mode because 
   // in order to write a record I need to read something else first
    file.create("fixedfile.txt",record.getRecordSize(),1);

    file.write(0,record); // Write the record in the offset 0

    file.close();

    file.open("fixedfile.txt","rb");

    file.read(0,readRecord); // Read record 0 and store it in a variable    

但它不起作用(实际上,它确实起作用,因为记录被写入并回读,但valgrind抱怨)。但是,如果我分别执行写和读的任务(即有两个实例——一个写,一个读),valgrind不会抱怨。

这是FixedLengthRecordFile该类的一些代码...

int FixedLengthRecordFile :: create (std::string fileName, int recSize, int p_maxRecs)
{
    // Initialize file attributes
    recordSize = recSize;
    maxRecs = p_maxRecs;


    file = fopen(fileName.c_str(),"wb+");
    if (file == NULL) 
        return RES_ERROR;

    if (initFileHeader() == RES_OK) 
    {
        if (initEmptyRecords() == RES_OK)
            return RES_OK;
    }

    return RES_ERROR;       
}

int FixedLengthRecordFile :: open (std::string fileName, std::string mode)
{
    file = fopen(fileName.c_str(),mode.c_str());
    if (file == NULL) {
        return RES_ERROR;
    }

    struct header head;
    if (getFileHeader(head) == RES_ERROR) {
        return RES_ERROR;
    }

    recordSize = head.h_recordSize;
    maxRecs = head.h_maxRecords;

    return RES_OK;
}

int FixedLengthRecordFile :: close ()
{   
    int result = fclose(file);

    if (result == 0) {
        std::cout << "File closed. " << std::endl;
        return RES_OK;
    }

    return RES_ERROR;   
}

int FixedLengthRecordFile :: write (const int numRec, const FixedLengthFieldsRecord & rec)
{
    int positioning = seek (numRec);
    if (positioning == RES_RECORD_DOESNT_EXIST || positioning == RES_ERROR)
        return RES_ERROR;

    char flag;
    int res = fread(&flag,sizeof(flag),1,file);
    if (res != 1) {
        std::cout << "Couldn't read record flag of " << numRec << std::endl;
        return RES_ERROR;
    }

    if (flag == 'O') // "occupied"
        return RES_RECORD_EXISTS;

    seek(numRec);

    return rec.write(file);
}

int FixedLengthRecordFile :: read (int numRec, FixedLengthFieldsRecord & rec) 
{
    int positioning = seek (numRec);
    if (positioning == RES_RECORD_DOESNT_EXIST)
        return RES_RECORD_DOESNT_EXIST;

    char flag;
    int res = fread(&flag,sizeof(char),1,file);
    if (res != 1) {
        std::cout << "Couldn't read record flag of " << numRec << std::endl;
        return RES_ERROR;
    }

    if (flag != 'O')
        return RES_RECORD_DOESNT_EXIST;

    return rec.read(file);
}

这是FixedLengthFieldsRecord课堂上的相关代码......

int FixedLengthFieldsRecord :: read (FILE* file)
{
    int res = fread(&record,recordSize,1,file);
    if (res != 1) {
        std::cout << "Couldn't read record. " << std::endl;
        return RES_ERROR;
    }

    std::cout << "Record read successfully! " << std::endl;
    return RES_OK;  
}

int FixedLengthFieldsRecord :: write (FILE* file) const
{
    char flag = 'O';

    int res = fwrite(&flag,sizeof(flag),1,file);
    if (res != 1) {
        std::cout << "Couldn't mark record as occupied. " << std::endl;
        return RES_ERROR;
    }

    res = fwrite(&record,recordSize,1,file);
    if (res != 1) {
        std::cout << "Couldn't write record. " << std::endl;
        return RES_ERROR;
    }

    std::cout << "Record written successfully! " << std::endl;
    return RES_OK;  
}

...这是来自的输出valgrind

X@notebook:~/Desktop/FixedRecordFile$ valgrind --leak-check=full --track-origins=yes --show-reachable=yes ./flrfile
Record written successfully! 
==20368== Syscall param write(buf) points to uninitialised byte(s)
==20368==    at 0x422A443: __write_nocancel (syscall-template.S:82)
==20368==    by 0x41BCBA4: _IO_file_write@@GLIBC_2.1 (fileops.c:1289)
==20368==    by 0x41BCA83: new_do_write (fileops.c:543)
==20368==    by 0x41BE0FD: _IO_do_write@@GLIBC_2.1 (fileops.c:516)
==20368==    by 0x8049DED: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==  Address 0x4035021 is not stack'd, malloc'd or (recently) free'd
==20368==  Uninitialised value was created by a stack allocation
==20368==    at 0x8049C97: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368== 
File closed. 
Record read successfully! 
==20368== Invalid read of size 4
==20368==    at 0x41B131C: fclose@@GLIBC_2.1 (iofclose.c:60)
==20368==    by 0x8049F09: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==20368== 
==20368== 
==20368== Process terminating with default action of signal 11 (SIGSEGV)
==20368==  Access not within mapped region at address 0x8
==20368==    at 0x41B131C: fclose@@GLIBC_2.1 (iofclose.c:60)
==20368==    by 0x8049F09: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==  If you believe this happened as a result of a stack
==20368==  overflow in your program's main thread (unlikely but
==20368==  possible), you can try to increase the size of the
==20368==  main thread stack using the --main-stacksize= flag.
==20368==  The main thread stack size used in this run was 8388608.
==20368== 
==20368== HEAP SUMMARY:
==20368==     in use at exit: 478 bytes in 5 blocks
==20368==   total heap usage: 22 allocs, 17 frees, 1,112 bytes allocated
==20368== 
==20368== 12 bytes in 1 blocks are still reachable in loss record 1 of 5
==20368==    at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20368==    by 0x8048D2E: FixedLengthFieldsRecord::FixedLengthFieldsRecord(int, int) (FixedLengthFieldsRecord.cpp:44)
==20368==    by 0x8049CDF: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368== 
==20368== 12 bytes in 1 blocks are definitely lost in loss record 2 of 5
==20368==    at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20368==    by 0x8048D2E: FixedLengthFieldsRecord::FixedLengthFieldsRecord(int, int) (FixedLengthFieldsRecord.cpp:44)
==20368==    by 0x8049E9D: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368== 
==20368== 51 bytes in 1 blocks are still reachable in loss record 3 of 5
==20368==    at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20368==    by 0x8048D14: FixedLengthFieldsRecord::FixedLengthFieldsRecord(int, int) (FixedLengthFieldsRecord.cpp:43)
==20368==    by 0x8049CDF: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368== 
==20368== 51 bytes in 1 blocks are definitely lost in loss record 4 of 5
==20368==    at 0x402A5E6: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20368==    by 0x8048D14: FixedLengthFieldsRecord::FixedLengthFieldsRecord(int, int) (FixedLengthFieldsRecord.cpp:43)
==20368==    by 0x8049E9D: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368== 
==20368== 352 bytes in 1 blocks are still reachable in loss record 5 of 5
==20368==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==20368==    by 0x41B1D17: __fopen_internal (iofopen.c:76)
==20368==    by 0x8049E53: createFileAddRecordAndRead() (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368==    by 0x8049FE3: main (in /home/X/Desktop/FixedRecordFile/flrfile)
==20368== 
==20368== LEAK SUMMARY:
==20368==    definitely lost: 63 bytes in 2 blocks
==20368==    indirectly lost: 0 bytes in 0 blocks
==20368==      possibly lost: 0 bytes in 0 blocks
==20368==    still reachable: 415 bytes in 3 blocks
==20368==         suppressed: 0 bytes in 0 blocks
==20368== 
==20368== For counts of detected and suppressed errors, rerun with: -v
==20368== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
4

1 回答 1

3

您的错误在于指针的使用。

res = fwrite(&record,recordSize,1,file);

应该

res = fwrite(record,recordSize,1,file);

因为记录已经是一个指针。

相似地

int res = fread(&record,recordSize,1,file);

应该

int res = fread(record,recordSize,1,file);

可能值得重命名该变量,因此很明显它是一个指针。在阅读代码时,我最初认为它是某种结构,所以我没有发现错误。

于 2013-04-03T06:25:44.153 回答