Search code examples
c++pointersbinaryfiles

Why pointer remains nullptr after initialisation


I wrote binary parser which reads and prints various info about file. I wish use E32ImageHeader data directly for speed reasons instead function calls.

I pass nullptr initialized variable and after function return variable remains nullptr. In GetFileLayout() gdb prints various field values for iHdr and some correctly other need revision.

Code looks correct but tools print "Header not recognized!!!", binary for test kf__speedups_SDK.pyd take here

main.cpp:

#include <iostream>
#include "e32info.h"
#include "e32parser.h"

using namespace std;

int main()
{
    E32ImageHeader *hdr = nullptr;
    E32Parser *parser = new E32Parser("AlternateReaderRecogE32.dll", hdr);
    parser->GetFileLayout(hdr);
    if(!hdr)
        cout << "Header not recognized!!!\n";
//    E32Info *f = new E32Info("h", "AlternateReaderRecogE32.dll");
//    f->Run();
    cout << "Hello world!" << endl;
    delete parser;
    return 0;
}

binary parser header file e32parser.h:

#ifndef E32PRODUCER_H
#define E32PRODUCER_H

class E32ImageHeader;

class E32Parser
{
    public:
        E32Parser(const char* aFilename, E32ImageHeader *aHdr);
        ~E32Parser();
        void GetFileLayout(E32ImageHeader *result);
    private:
        void ReadFile();

    private:
        E32ImageHeader *iHdr = nullptr;

        const char *iFileName = nullptr;
        char *iBufferedFile = nullptr;
        size_t iE32Lenth = 0;
}

how it works e32parser.cpp:

#include <fstream>
#include <cstring>
#include <cstdlib>

#include "e32common.h"
#include "e32parser.h"

E32Parser::E32Parser(const char* aFilename, E32ImageHeader *aHdr):
    iHdr(aHdr), iFileName(aFilename)
{
}

E32Parser::~E32Parser()
{
    delete iBufferedFile;
}

Read binary file to internal buffer

void E32Parser::ReadFile()
{
    std::fstream fs(iFileName, fs.binary | fs.in);
    if(!fs)
        throw;
    fs.seekg(0, fs.end);
    int lenth = fs.tellg();
    fs.seekg(0, fs.beg);

    iBufferedFile = new char[lenth];
    fs.read(iBufferedFile, lenth);
    fs.close();;
}

void E32Parser::GetFileLayout(E32ImageHeader *result)
{
    ReadFile();

    iHdr = (E32ImageHeader*)iBufferedFile;
    result = (E32ImageHeader*)iBufferedFile;
}

Solution

  • Your issue, as pointed out in the comments, is that you are modifying a COPY of the pointer that you pass in. Consider this small example:

    void modify(int* p) { p = new int{10}; }
    
    int main()
    {
        int* n = nullptr;
        modify(n);
        if (n)
            std::cout << *n;
    }
    

    The output of this program is nothing (and it leaks memory). modify doesn't change the original value, it changes a copy of n. The fix to this, and your program, is to pass the pointer by reference.

    void modify(int*& p) { p = new int{10}; }
    

    and

    void E32Parser::GetFileLayout(E32ImageHeader*& result)
    

    However, I'd argue a better fix is just return the pointer, to prevent this issue:

    E32ImageHeader* E32Parser::GetFileLayout()
    {
        ...
        iHdr = (E32ImageHeader*)iBufferedFile;
        return iHdr;
    }
    

    But since iHdr is passed in to E32Parser, you could change it to be a reference instead