Search code examples
c++linkerlinker-errorsunresolved-external

Linker can't find a namespace's functions


See code below. There's something wrong with it, because the linker is complaining it can't find the Memory's functions, but I can't figure out why.

memory.h

#pragma once
#include "includes.h" //it just includes other strandard headers.

class MemoryUnit
{
public:
    MemoryUnit() {}
    virtual int getValue() = 0;
    virtual int getSize() = 0;
    virtual void setValue(int) = 0;
    virtual ~MemoryUnit() {};
};
class Byte : public MemoryUnit
{
    int value;
public:
    static int size;
    Byte(int byte) :value(byte) {};
    int getSize() { return size; }
    int getValue() { return value; };
    void setValue(int byte) { value = byte; }
    ~Byte() {};
};
namespace Memory
{
    extern int size;
    extern MemoryUnit** map;
    void checkAddress(int address);
    int read(int adress);
    MemoryUnit* getOperation(int address);
    void write(int adress, MemoryUnit* data);
    void writeByte(int adress, int data);
}

memory.cpp

#include "includes.h"
#include "memory.h"
#include "simulator.h" // it contains only externed constants.

namespace Memory
{
    int size = 0;
    MemoryUnit** map = NULL;
    inline MemoryUnit* getOperation(int address)
    {
        return map[address];
    }
    inline void checkAddress(int address)
    {
        if (address < 0 || address >= MAX_MEMORY_SIZE)
            throw std::out_of_range("Invalid memory address.");
    }
    inline int read(int address)
    {
        checkAddress(address);
        return map[address]->getValue();
    }
    inline void write(int address, MemoryUnit* data)
    {
        checkAddress(address);
        delete map[address];
        map[address] = data;
    }
    inline void writeByte(int address, int data)
    {
        checkAddress(address);
        map[address]->setValue(data);
    }
}

Everywhere the class/namespace memory.h declares is includes memory.h. Is here anything wrong in the code below?

Edit: I'm using Visual Studio 2015. Errors I got when building the project:

LNK1120 5 unresolved externals  simulator.exe
LNK2019 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" referenced in function "void __cdecl ALU::setFlags(int)" alu.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" cu.obj
LNK2019 unresolved external symbol "class MemoryUnit * __cdecl Memory::getOperation(int)" referenced in function "void __cdecl CU::run(void)" cu.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" helpers.obj
LNK2019 unresolved external symbol "void __cdecl Memory::write(int,class MemoryUnit *)" referenced in function "void __cdecl readProgramCommands(void)" helpers.obj
LNK2001 unresolved external symbol "public: virtual int __thiscall MemoryPointer::getValue(void)" helpers.obj
LNK2001 unresolved external symbol "public: virtual int __thiscall IndirectMemoryPointer::getAddress(void)" helpers.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" main.obj

alu.h and alu.cpp for the first error:

//alu.h
#pragma once
#include "includes.h"
#include "operation.h"
namespace ALU
{
    int operation(Operation* op);
    void setFlags(int result);
}
//alu.cpp
#include "includes.h"
#include "simulator.h"
#include "alu.h"
#include "memory.h"
#include "operation.h"
namespace ALU
{
    int operation(Operation* operation)
    {
        // ...
        setFlags(result);
        return result;
    }
    inline void setFlags(int result)
    {
        Memory::writeByte(FLAG_Z, result == 0);
        // ...
    }
}

Solution

  • When you're using inline functions or methods, their definitions should be visible for every source unit that uses them. You defined your inline functions in Memory.cpp, that's why you get 'unresolved' linker error.

    To fix your problem you can:

    1. Remove inline modifier and keep functions definitions in Memory.cpp.

    2. Keep inline modifier but move functions definitions to Memory.h.