karthikkk
karthikkk

Reputation: 27

Cannot open a file through fopen()

Im working on making a simulator with c++, for which I need to read files.

my directory looks something like this

proj
------>bin        #stores the executable
------>include    #stroes the external library includefiles
------>lib        #stores the lib files of the libraries
------>obj        #stores the .o files
------>src        #source files
makefile


my make file looks this

CC = g++
OUT = chip8
ODIR = ./obj
SDIR = ./src
OUTDIR = ./bin
IDIR = ./include
LDIR = ./lib
libs = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
OBJS = $(patsubst $(SDIR)/%.cpp,$(ODIR)/%.o,$(wildcard $(SDIR)/*.cpp))
vpath %.cpp $(SDIR):$(SDIR)/Chip8

$(ODIR)/%.o : %.cpp
    $(CC) -c -I $(IDIR) -o $@ $^

$(OUTDIR)/% : $(wildcard obj/*.o)
    $(CC) -L $(LDIR) -o $@ $^ $(libs)

.PHONY : run

run :
    $(OUTDIR)/$(OUT)


these are my source files

main.cpp


#include <iostream>
#include "Chip8/RomFileReader.h"


int main(){

    RomReader romReader;

    if(romReader.OpenFile("picture.ch8") == -1){
        std::cout<<"could not open file !"<<std::endl;
        return EXIT_FAILURE;
    }

    romReader.GetRom();

    uint8_t * rom = romReader.ReturnRom();
    int size = romReader.GetRomSize();

    for(int i = 0; i<size; i++)
        std::cout<<rom[i]<<std::endl;

    free(rom);

    romReader.FreeRom();
    romReader.CloseReader();

}

ReadRomFile.h

#pragma once 

#include <iostream>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>

class RomReader{

private :

    FILE * m_Reader;
    uint8_t * m_Rom; 

public : 

    int OpenFile(const char * fileName);
    void GetRom();
    void FreeRom();
    uint8_t * ReturnRom();
    void CloseReader();
    int GetRomSize();

};

RomFileReader.cpp


#include "RomFileReader.h"

int RomReader :: OpenFile(const char * fileName){

    m_Reader = fopen(fileName,"rb");

    if(m_Reader == NULL){
        return -1;
    } else 
        return 1;

}

int RomReader :: GetRomSize(){
    
    int start = ftell(m_Reader);
    fseek(m_Reader,0,SEEK_END);
    int end = ftell(m_Reader);
    fseek(m_Reader,0,SEEK_SET);

    int size = end - size;

    return size;

}

void RomReader :: GetRom(){

    int size = GetRomSize();

    if(m_Rom == NULL){
        m_Rom = new uint8_t[size];
    }

    fread(m_Rom,1,size,m_Reader);

}

void RomReader :: FreeRom(){

    free(m_Rom);

}

uint8_t * RomReader :: ReturnRom(){

    return m_Rom;

}


void RomReader :: CloseReader(){

    fclose(m_Reader);

}

this is the error I'm getting


./bin/chip8
could not open file !      
make: *** [run] Error 1   

I could use fstream but I'm more comfortable and confident in using FILE instead, I had done something similar in c and it worked without any issue.

I'm really not able to point at what is exactly not working.

my picture.ch8 is in the bin folder along with the executable, yet I get this error. What is it that I'm missing exactly?

Upvotes: 0

Views: 194

Answers (2)

MiniMik
MiniMik

Reputation: 268

Your main is calling

romReader.FreeRom();

I think m_Rom is not NULL. So the memory get freed, so the memory exception getting fired?!?

Set it to NULL in a constructor of your class:

class RomReader {

...
public : 
  RomReader() { m_Rom = NULL; };
  ~RomReader() { if ( m_Rom != NULL ) delete [] m_Rom; };
...
}

Upvotes: 2

Chris Dodd
Chris Dodd

Reputation: 126203

The basic problem you have is that wildcard expands to the files that exist when make reads the makefile. So when you build with a clean tree (where the obj directory is empty), it expands to nothing, so nothing gets built.

The upshot is that wildcard cannot be usefully used with intermediate files generated as part of your build as they might not exist yet when you build. It is only useful for finding source files.

You need instead something like

$(OUTDIR)/$(OUT): $(patsubst src/%.cpp, obj/%.o, $(wildcard src/*.cpp)) $(patsubst src/Chip8/%.cpp, obj/%.o, $(wildcard src/Chip8/*.cpp))

You also probably want to have your run target depend on the executable

run: $(OUTDIR)/$(OUT)

otherwise it will not (re)build it when you try to run.

Upvotes: 1

Related Questions