I am getting a runtime access violation error when defining a static class variable. I'm not quite sure what is exactly going wrong; is the static function I am calling not implemented at the time of calling, something else?
What is going wrong and how can I fix this?
Runtime error (see code below for the line that the error occurs on):
0xC0000005: Access violation reading location 0x00000000.
Code:
// Status.h
class Status
{
public:
// Static Properties//
static const Status CS_SUCCESS;
// Static Functions //
static const Status registerState(const tstring &stateMsg)
{
int nextStateTmp = nextState + 1;
auto res = states.emplace(std::make_pair(nextStateTmp, stateMsg));
return (res.second) ? Status(++nextState) : Status(res.first->first);
}
private:
static std::unordered_map<STATE, tstring> states;
static STATE nextState;
};
// Status.cpp
#include "stdafx.h"
#include "Status.h"
// Class Property Implementation //
State Status::nextState = 50000;
std::unordered_map<STATE, tstring> Status::states;
const Status S_SUCCESS = Status::registerState(_T("Success"));
// IApp.h
class IApp : protected Component
{
public:
static const Status S_APP_EXIT;
static const Status S_UNREGISTERED_EVT;
...
};
// IApp.cpp
#include "stdafx.h"
#include "../EventDelegate.h"
#include "../Component.h"
#include "IApp.h"
// Class Property Implementation //
const Status IApp::S_APP_EXIT = CStatus::registerState(_T("IApp exit")); // Runtime error: 0xC0000005: Access violation reading location 0x00000000.
const Status IApp::S_UNREGISTERED_EVT = CStatus::registerState(_T("No components registered for this event"));
Some static variables like S_APP_EXIT depend on other static variables (e.g. nextState) for their initialization.
Read about the static initialization order fiasco and fix your code accordingly (making nextState a private variable?). You might even think of using the Construct On First Use Idiom (explained in the other FAQ here).
Anyway I wouldn't generally advise keeping all those variables static, but it's quite hard to tell from just the excerpt you posted (where is CS_SUCCESS defined?).
Related
I'm having a hard time figuring out how to solve this C2027 compiler error:
"A type cannot be used until it is defined. To resolve the error, be sure the type is fully defined before referencing it".
This is CPU.h:
// CPU.h
#include "Register.h"
class Register;
class CPU
{
public:
static const enum class Flag { CARRY = 4, HALF_CARRY, SUBTRACT, ZERO };
private:
Register A;
};
And this is Register.h:
// Register.h
#include "CPU.h"
class CPU;
class Register
{
void foo(const CPU::Flag& flag); // error C2027
};
So I now that this error is because CPU class hasn't initialize yet and I'm aware of the option the put the Flag Enum class outside of CPU class. But I wonder if there is another option so I can keep Flag inside CPU.h
(for logic purposes).
Thanks :)
So I've got this interface class that I include, both in the dll and the client project
// InterfaceClass.h
#pragma once
class InterfaceClass
{
public:
virtual void Update() = 0;
};
This is the dll class that calls one of its own methods inside update
// DLLClassThatDoesSomething.cpp
#include "InterfaceClass.h"
#include <iostream>
#include <string>
class __declspec(dllexport) DLLClass : public InterfaceClass
{
public:
void Update()
{
std::cout << this->GetString();
}
std::string& GetString()
{
std::string thestring = "bruhmoment";
return thestring;
}
};
extern "C"
{
__declspec(dllexport) InterfaceClass* CreateInstance()
{
return new DLLClass();
}
}
And this is the "Client" project
// main.cpp
#include "InterfaceClass.h"
#include <Windows.h>
typedef InterfaceClass* (__cdecl *Class) ();
int main()
{
HINSTANCE dll = LoadLibrary(L"DLLClass.dll");
Class klass = (Class)GetProcAddress(dll, "CreateInstance");
InterfaceClass* IKlass = klass();
IKlass->Update();
FreeLibrary(dll);
return 0;
}
The moment I call IKlass->Update() I get an exception for Access Memory Violation because of the DLLClass calling its own method.
I haven't tried anything since I barely know how to load a DLL on runtime and I've used this nifty tutorial
How can I let it call the method and not get thrown an exception? I'm trying to let ppl that will create mods for my game create their own mods with their custom classes for bosses, mobs and etc. in DLLs.
EDIT:
Turns out it was a syntax mistake on my end. Instead of return new DLLClass;, it had to be return new DLLClass();. After fixing it, it works as intended.
You return a reference to a local variable thestring, and by the time you try to access it in
std::cout << this->GetString(), referenced data is already destroyed. In fact, it is destroyed right after the end of enclosing scope of compound statement where the variable was declared.
It may "appear" to work sometimes due to the stack not being overwritten yet, but eventually it will fail miserably like it did in your case. This triggers UB (undefined behavior).
I have a confusing issue using a static member variable as a default parameter. Since the same language construct works in a different place, it might be related to project (DLL) inter-dependencies. So please accept my apologies if my example is too complex, but I should draw the whole picture since I do not have any idea what is wrong.
I have a base class (representing kind of an error code)
ErrorBase.h
class ErrorBase
{
public:
typedef unsigned long ErrorCode;
/// here go the error codes. For reasons I do not want to explain, I cannot use an enumeration here.
static const ErrorCode ERROR_UNINITIALIZED;
static const ErrorCode ERROR_OK;
///...and so on
ErrorBase(ErrorCode theCode = ERROR_UNINITIALIZED);
};
...and in ErrorBase.cpp, I am assigning values to the codes...
const ErrorBase::ErrorCode ErrorBase::ERROR_UNINITIALIZED = 0xffffffff;
const ErrorBase::ErrorCode ErrorBase::ERROR_OK = 0x0;
//.. and so on...
ErrorBase is exported from a DLL which provides some general purpose classes to our project
Now I am deriving another error class for more specific errors which has additional attributes specific for the particular type of error. The class SpecificError is part of a different DLL which links to the general purpose DLL containing ErrorBase. I have not included the dllimport/dllexport shebang, but we are using this all over the place and it works in all cases. If you have doubts, I can edit my code example.
SpecificError.h
class SpecificError : public ErrorBase
{
public:
static const ErrorCode SPECIFIC_ERROR_UNINITIALIZED;
static const ErrorCode SPECIFIC_ERROR_SOMETHING_WENT_WRONG;
SpecificError(ErrorCode theCode = SPECIFIC_ERROR_UNINITIALIZED);
};
... and in the SpecificError.cpp I am defining these values:
const SpecificError::ErrorCode SpecificError::SPECIFIC_ERROR_UNINITIALIZED = ErrorBase::ERROR_UNINITIALIZED;
Like ErrorBase, SpecificError is exported from the DLL handling specific functionality. Note that both error classes declare a constructor using the "UNINITIALIZED" value as a default for the error code.
Now I have a program being dependent on both DLLs, thus linking to both of them through the corresponding import libraries. This program includes ErrorBase.h and SpecificError.h. It does not seem to have any problems with ErrorCode.h, but about SpecificError.h I am receiving an
LNK2001 unresolved external symbol SpecificError::ErrorCode SpecificError::SPECIFIC_ERROR_UNINITIALIZED referenced in main.obj.
(remark: main.cpp does not explicitly use SpecificError, it just includes the header file).
I was able to work-around the problem by removing the default parameter from the SpecificError constructor and declaring a default constructor which in its implementation calls the inherited constructor of ErrorBase passing SPECIFIC_ERROR_UNINITIALIZED to it. This leads me to the assumption that the symbol SPECIFIC_ERROR_UNINITIALIZED is properly declared and defined but cannot be used as a parameter default. However, this seems to apply to SpecificError only, everything seems fine in ErrorBase.
Toolset: I am using Visual C++ 2017 as a compiler.
I recreated the linked error. Make the following changes to your files and it should work just fine based on the code snippets that you showed above:
SpecificError.cpp
// I sent theCode to the Base class
SpecificError::SpecificError(ErrorCode theCode) : ErrorBase(theCode)
{
// ...
}
In ErrorBase.cpp I just added the constructor but you probably already have this:
ErrorBase::ErrorBase(ErrorCode theCode)
{
// ...
}
After I did this, I had to also move the initializations of the static consts to the .h from the .cpp files. Then I tested the code by doing:
SpecificError e; // theCode ends up being 0xffffffff
SpecificError e1(20); // theCode ends up being 20
I hope that this helps you.
Here is what my ErrorBase.cpp looks like:
#pragma once
#include"ErrorBase.h"
#include<iostream>
ErrorBase::ErrorBase(ErrorCode theCode) {
std::cout << theCode << std::endl;
}
ErrorBase.h:
#pragma once
class ErrorBase
{
public:
typedef unsigned long ErrorCode;
static const ErrorCode ERROR_UNINITIALIZED = 0xffffffff;
static const ErrorCode ERROR_OK = 0x0;
ErrorBase(const ErrorCode = ERROR_UNINITIALIZED);
};
SpecificError.cpp:
#pragma once
#include"SpecificError.h"
SpecificError::SpecificError(ErrorCode theCode) : ErrorBase(theCode)
{
}
SpecificError.h:
#pragma once
#include "ErrorBase.h"
class SpecificError : public ErrorBase
{
public:
static const ErrorCode SPECIFIC_ERROR_UNINITIALIZED = ErrorBase::ERROR_UNINITIALIZED;
static const ErrorCode SPECIFIC_ERROR_SOMETHING_WENT_WRONG = -42;
SpecificError(ErrorCode theCode = SPECIFIC_ERROR_UNINITIALIZED);
};
I tried this and it is working, the class name was missing in ErrorBase.cpp
const ErrorBase::ErrorCode ErrorBase::ERROR_UNINITIALIZED = 0xffffffff;
const ErrorBase::ErrorCode ErrorBase::ERROR_OK = 0x0;
If still not working then let me know.
You doing it wrong. The linker error means that it doesn't know where to get your constant value. You should use dynamic linkage with a first DLL. Let me show
Example of C++ class export:
C++ How to export a static class member from a dll?
And your code should be changed:
ErrorBase.h
#ifndef MAIN_DLL
#define MAIN_DLL 1 // or you can add MAIN_DLL definition to the your first project Macroses
#endif
#if MAIN_DLL
#define ERROR_API __declspec(dllexport) // export things to other modules
#else
#define ERROR_API __declspec(dllimport) // import things from the external DLL
#endif
class ERROR_API ErrorBase
{
public:
typedef unsigned long ErrorCode;
/// here go the error codes. For reasons I do not want to explain, I cannot use an enumeration here.
static const ErrorCode ERROR_UNINITIALIZED;
static const ErrorCode ERROR_OK;
///...and so on
ErrorBase(ErrorCode theCode = ERROR_UNINITIALIZED);
};
SpecificError.h
#pragma once
#define MAIN_DLL 0
#include "../Dll_stack_ovfl1/ErrorBase.h" // change it to your path
class SpecificError : public ErrorBase
{
public:
static const ErrorCode SPECIFIC_ERROR_UNINITIALIZED;
static const ErrorCode SPECIFIC_ERROR_SOMETHING_WENT_WRONG;
SpecificError(ErrorCode theCode = SPECIFIC_ERROR_UNINITIALIZED);
};
And the final step, configure the second DLL project to link it with exports of the first one:
Configuration Properties/Linker/Input/Additional dependencies
Add something like "$(SolutionDir)$(Configuration)\ErrorBase.lib"
Once again its just example, I don't know the real path of "lib" file and your project name for ErrorBase DLL - change it to your specific.
When I'm trying to run executable compiled using VS2017 I catch
Exception thrown at 0x00007FFF05BC1063 (msvcp140d.dll) in a.exe: 0xC0000005: Access violation reading location 0x0000000000000000. immediately after launching.
After debugging i figured out that it happens when I'm trying to lock static mutex _coutMutex. How can I fix it because when I have compiled using mingw it worked fine. Here is part of my code:
Game.hpp:
#include "Logger.hpp"
class Game
{
public:
static Logger logger;
};
Game.cpp:
#include "Game.hpp"
Logger Game::logger{ "logs/client", Logger::LoggingLevels::Info,
Logger::LoggingLevels::Trace, 2, 100 };
Logger.hpp:
#include <mutex>
class Logger
{
public:
Logger(std::string path, short consoleLoggingLevel, short
fileLoggingLevel, uint32_t count, size_t maxSize);
enum LoggingLevels : short
{
Off = 0,
Fatal = 1,
Error = 2,
Warn = 3,
Info = 4,
Debug = 5,
Trace = 6
};
void _addToQueue(std::string data);
private:
static std::mutex _coutMutex;
};
Logger.cpp:
std::mutex Logger::_coutMutex;
Logger::Logger(std::string path, short consoleLoggingLevel,
short fileLoggingLevel, uint32_t count, size_t maxSize)
{
_addToQueue("dd/mm/yyyy hh:mm:ss.sss\n");
}
void Logger::_addToQueue(std::string data)
{
_coutMutex.lock();
std::cout << data;
_coutMutex.unlock();
}
main.cpp:
#include "Logger.hpp"
#include "Game.hpp"
int main()
{
Game game;
}
As Richard Critten suggests, this must be the global initialisation order problem.
You have 2 global variables, logger and _coutMutex, and these are in a different compilation unit. The order which they are initialized is not defined.
When Logger's constructor runs, _coutMutex is not initialized yet, but _addToQueue wants to use it.
You could have three solutions:
Avoid using global objects. Or avoid using global constructors which do something serious (if you remove _addToQueue from logger constructor, it will work).
put these global variables into one compilation unit, in correct order
add an accessor function for _coutMutex, and define mutex inside of it (as a static variable). Beware of this solution, as it has its drawbacks (speed, thread safety)
I'm writing a multi-threaded server using boost::asio (for sockets), boost::thread (for threading), libconfig++ (for configuration files reading) and protocol buffers (for the protocol implementation).
The server follows more or less this route: main() -> creates an Application object -> runs application object. Application loads configuration file, then creates the server object (which is passed the configuration class as a const). Server object configures itself and binds the port, starts accepting, blah. Whenever a new client is detected, the server creates a new Client object, and then creates a thread running the client's connection handler.
All of this is to explain that the configuration file is loaded from my Application class, and then passed all the way down to my Client class. This shouldn't pose any kind of trouble if the libconfig object was passed directly all the way to the Client, yet as we all know, multi-threading implies that memory corrupts when accessed simultaneously by two or more threads.
The way to solve this was discussed in other post and ended up with the implementation of a wrapper which automagically solves the mutex problem.
The magical class
app_config.h
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_ 1
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/noncopyable.hpp>
#include <libconfig.h++>
#include <string>
namespace BBCP {
namespace App {
class ConfigLock;
class Config {
public:
friend class BBCP::App::ConfigLock;
Config(std::string const &file) :
cfg(new libconfig::Config()),
mutex(new boost::mutex())
{
cfg->readFile(file.c_str());
}
private:
boost::shared_ptr<libconfig::Config> cfg;
boost::shared_ptr<boost::mutex> mutex;
};
class Server;
class Client;
class ConfigLock : boost::noncopyable {
public:
ConfigLock(BBCP::App::Config const &wrapper) :
cfg(wrapper.cfg),
mutex(wrapper.mutex),
lock(new LockType(*mutex))
{ }
libconfig::Config &get() throw() { return *cfg; };
private:
boost::shared_ptr<libconfig::Config> cfg;
boost::shared_ptr<boost::mutex> mutex;
typedef boost::lock_guard<boost::mutex> LockType;
boost::shared_ptr<LockType> lock;
};
}
}
#endif
For lazy people, this class consists of... well, two classes (irony?): BBCP::App::Config and BBCP::App::ConfigLock. BBCP::App::Config simply loads a file, while BBCP::App::ConfigLock takes a BBCP::App::Config as an argument, and then locks BBCP::App::Config's mutex. Once the lock has been created, one calls BBCP::App::ConfigLock::get, which returns a reference to the libconfig::Config object!.
THE problem
Well:
server.cpp:
void BBCP::App::Server::startAccept() {
newClient.reset(new BBCP::App::Client(io_service, config_wrapper));
acceptor.async_accept(newClient->getSocket(), boost::bind(&BBCP::App::Server::acceptHandler, this, boost::asio::placeholders::error));
}
This function creates a new client object, loaded with the boost::asio::io_service object and BBCP::App::Config object.
server.cpp
void BBCP::App::Server::acceptHandler(boost::system::error_code const &e) {
if (!acceptor.is_open()) {
// ARR ERROR!
return;
}
if (!e) {
client_pool.create_thread(*newClient);
}
else {
// HANDLE ME ERROR
throw;
}
startAccept();
}
This function creates a new thread or (not implemented yet) errors in case of... well, errors, then starts the accept loop again.
Client code mostly doesn't matter until this part:
client.cpp:
void BBCP::App::Client::parseBody() {
BBCP::Protocol::Header header;
BBCP::Protocol::Hello hello;
boost::scoped_ptr<BBCP::App::ConfigLock> lock;
libconfig::Config *cfg;
(...)
switch ((enum BBCP::Protocol::PacketType)header.type()) {
case BBCP::Protocol::HELLO:
(...)
// config_wrapper is a private variable in the client class!
lock.reset(new BBCP::App::ConfigLock(config_wrapper));
// ARRRRRRR HERE BE DRAGOONS!!
*cfg = lock->get();
(...)
lock.reset();
break;
(...)
}
(...)
}
Well, truth be told, I didn't expect this kind of error:
/usr/include/libconfig.h++: In member function ‘void BBCP::App::Client::parseBody()’:
/usr/include/libconfig.h++:338:13: error: ‘libconfig::Config& libconfig::Config::operator=(const libconfig::Config&)’ is private
client.cpp:64:30: error: within this context
client.cpp:71:21: error: request for member ‘exists’ in ‘cfg’, which is of non-class type ‘libconfig::Config*’
client.cpp:77:51: error: request for member ‘lookup’ in ‘cfg’, which is of non-class type ‘libconfig::Config*’
But here it is, and I need some way to solve it :(. I've tried making BBCP::App::Client a friend class of BBCP::App::ConfigLock, but then it went like:
In file included from ../include/app_config.h:4:0,
from ../include/app_main.h:6,
from main.cpp:18:
../include/app_client.h:15:53: error: ‘BBCP::App::Config’ has not been declared
In file included from ../include/app_config.h:4:0,
from ../include/app_main.h:6,
from main.cpp:18:
../include/app_client.h:32:5: error: ‘Config’ in namespace ‘BBCP::App’ does not name a type
In file included from ../include/app_config.h:4:0,
from ../include/app_main.h:6,
from main.cpp:18:
../include/app_client.h: In constructor ‘BBCP::App::Client::Client(boost::asio::io_service&, const int&)’:
../include/app_client.h:15:120: error: class ‘BBCP::App::Client’ does not have any field named ‘config_wrapper’
And then I went like O_O, so I just gave up and came here, once again looking for some über C++ guru hackz0r's help and scolding for doing such a misdeed as trying to access another class's private members is.
The first thing is figuring out if you are going in the right direction, and the next step is getting there.
Why is the assignment operator of the Config type private? By default the compiler generated assignment operator is public, so if it has been declared as private, chances are that there is a reason for the object not to be copied, or else you should make it public and the problem would no longer be a problem.
As of your particular problem after adding the friend declaration, it seems to indicate that you have missed including the header where the Config type is declared/defined. And then there are some more errors in the code (a member that has not been defined - result of the previous error?), or in the original code trying to access the object referred by a pointer without dereferencing it...
You probably wanted to store a pointer to the config object in cfg instead of creating a copy (and dereferencing an uninitialized pointer):
cfg = &local->get();