constructor not getting called? - c++

Ive been staring at my code and I can't figure out why on earth my constructor is not gettign called.
It's just ignoring my constructor completely (i've check with stepping with debugger).
Here's my testapp:
using namespace MyEngine;
int _tmain(int argc, _TCHAR* argv[])
{
TestManager* testMgr = new TestManager();
testMgr->RunAllTests();
delete testMgr;
getchar();
return 0;
}
TestManager.h:
namespace MyEngine
{
class TestManager
{
public:
TestManager();
TestManager(uint64_t RepeatTimes);
~TestManager();
bool RunAllTests();
bool RunMemoryTests();
private:
Engine* mEngine;
ILogManager* mLogger;
MemoryTestManager* mMemTestMgr;
uint64_t mRepeatTimes;
};
}
and TestManager.cpp
namespace MyEngine
{
TestManager::TestManager()
{
TestManager(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
TestManager::~TestManager()
{
}
/* Runs all testing modules */
bool TestManager::RunAllTests()
{
bool res = true;
/* Init Engine */
if(mEngine->Init(0,0,0))
{
res = true;
res && mEngine->GetRenderManager()->Init();
res && mLogger->Init(true,true);
res && mEngine->GetMemoryManager()->Init(false);
}
else
return false;
/* Start Engine */
mEngine->Start();
/* Get logger */
mLogger = mEngine->GetLogger();
/* Run Memory Tests */
res &= RunMemoryTests();
if (res)
mLogger->LogInfo("TEST: TESTING SUCCESSFULL");
else
mLogger->LogError("TEST: TESTING FAILED");
return res;
}
/* Runs all memory tests */
bool TestManager::RunMemoryTests()
{
bool res = true;
res &= mMemTestMgr->AllocateTest();
res &= mMemTestMgr->ReferenceTest();
if (res)
mLogger->LogInfo("TEST: RunMemoryTests SUCCESSFULL");
else
mLogger->LogError("TEST: RunMemoryTests FAILED");
return res;
}
}

You cant call another constructor from the same class. I'd refactor the init code into a separate method and call it from both constructors:
namespace MyEngine
{
TestManager::TestManager()
{
Init(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
Init(RepeatTimes);
}
void TestManager::Init(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
}

When you call TestManager(1); inside your TestManager::TestManager() constructor, you're creating another instance of TestManager, using the constructor TestManager::TestManager(uint64_t).
You can't do this on C++, you have to create either a init method, were you set the instance variables to whatever you want, or use optional parameters:
TestManager(uint64_t RepeatTimes = 0);
Then, if you create an instance of TestManager without arguments, you will be calling the TestManager::TestManager(uint64_t)constructor with 0 as the uint64_t argument.

you can't call a default constructor from a overloaded constructor. Why don't you simply create you object like this:
TestManager* testMgr = new TestManager(1);

Using a default argument (as per fontanini's answer) will do what you want in this case.
But if this is a simplified example and you really do want to delegate to another constructor, then that's not possible in C++03 - the line TestManager(1) just constructs a temporary object which goes unused (and the line will probably be optimized out unless the TestManager(uint64_t) constructor has side effects).
However, you can do what you're aiming for here with a C++11 compiler and the following syntax:
TestManager::TestManager() :
TestManager(1)
{
}

Related

How does this default template struct assignment work? [duplicate]

This question already has answers here:
Arrow operator (->) in function heading
(3 answers)
Closed 4 months ago.
I have been digging into some embedded C++ firmware used by DaveJone's (eevblog) uSupply project
https://gitlab.com/eevblog/usupply-firmware.
There is common pattern of code that I just can't quite wrap my head around what is happening.
For example:
In the file "RegistersRCC.hpp" there is a template struct:
template <std::size_t A>
struct CR : public General::u32_reg<A>
{
using base_t = General::u32_reg<A>;
using base_t::base_t;
//PLL register bits
auto PLLRDY () { return base_t::template Actual<RCC_CR_PLLRDY>(); }
auto PLLON () { return base_t::template Actual<RCC_CR_PLLON>(); }
//PLL Management functions
void EnablePLL() noexcept
{
if ( not PLLON().Get() )
{
PLLON() = true;
while ( not PLLRDY().Get() );
}
}
void DisablePLL() noexcept
{
if ( PLLON().Get() )
{
PLLON() = false;
while ( PLLRDY().Get() );
}
}
//Enable clock security
auto CSSON () { return base_t::template Actual<RCC_CR_CSSON>(); }
//High speed external oscillator bits
auto HSEBYP () { return base_t::template Actual<RCC_CR_HSEBYP>(); }
auto HSERDY () { return base_t::template Actual<RCC_CR_HSERDY>(); }
auto HSEON () { return base_t::template Actual<RCC_CR_HSEON>(); }
//HSE Management functions
void EnableHSE()
{
if ( not HSEON().Get() )
{
HSEON() = true; //Enable the clock
while( not HSERDY().Get() ); //Wait for it to stable
}
}
void DisableHSE()
{
if ( HSEON().Get() )
{
HSEON() = false; //Disable the clock
while( HSERDY().Get() ); //Wait for it to disable
}
}
void ConnectHSE()
{
HSEBYP() = false; //Connect it to system
}
void BypassHSE()
{
HSEBYP() = true; //Disconnect it to system
}
//High speed internal oscillator bits
auto HSICAL () { return base_t::template Actual<RCC_CR_HSICAL>(); }
auto HSITRIM() { return base_t::template Actual<RCC_CR_HSITRIM>(); }
auto HSIRDY () { return base_t::template Actual<RCC_CR_HSIRDY>(); }
auto HSION () { return base_t::template Actual<RCC_CR_HSION>(); }
//HSI Management functions, No calibration provided
// these chips are factory calibrated
void EnableHSI()
{
if (not HSION().Get())
{
HSION() = true;
while (!HSIRDY());
}
}
void DisableHSI()
{
if ( HSION().Get() )
{
HSION() = false;
while (HSIRDY());
}
}
};
This struct exists in the namespace:
namespace Peripherals::RCCGeneral
{
}
Within the same namespace/header file there is this "Default"
CR() -> CR<RCC_BASE + offsetof(RCC_TypeDef, CR)>;
I think this is where my gap in understanding lies. What is happening here? Specifically with the lvalue and arrow operator, and why this is located within the header.
Within the files that utilize the RCCRegisters you see usages like:
CR{}.DisablePLL();
This is called class template argument deduction(CTAD) which allows writing deduction guides to the compiler about how to deduce the template arguments from constructor calls.
It is a handy C++17 addition that saves on typing:
std::vector x{1.,2.,3.} //deduces std::vector<double>
C++14 and older requires to explicitly write std::vector<double> which gets tedious and too verbose for some more complex examples.
In this case, the guide
CR() -> CR<RCC_BASE + offsetof(RCC_TypeDef, CR)>;
specifies that the default constructor should deduce A template parameter to RCC_BASE + offsetof(RCC_TypeDef, CR).
The same could have been achieved by simply using a default template argument:
template <std::size_t A = default_value>
struct CR : public General::u32_reg<A>{ ... };
But here comes the catch, offsetof(RCC_TypeDef, CR) is not valid here because at this line, CR doesn't exist yet.
So my assumption is this a fix around this limitation to allow making the default value depend on the class definition itself, quite clever I think.

C++ Difficulty Creating Instance of Class within Singleton Class

I have a fairly good template (as in snippet of code) I pull out whenever I need a singleton class. I am now trying to apply it within my project to allow me to control a single instance of a web server. I can make a web server without encasing it in my class. When I try to encase it within the class I'm apparently too unskilled to pull it off.
I've tried the obvious Googling and searching here. I've read relevant posts. I am sure this does not mean I have a unique problem, just that I've not figured out the right way to fix it. Here's what I am working with:
webserver.h:
#include <ESP8266WebServer.h>
#include <FS.h>
class WebServer {
private:
// Singleton Declarations
static bool instanceFlag;
static WebServer *single;
WebServer() {}
// Other Declarations
FS *filesystem;
ESP8266WebServer server();
String getContentType(String);
bool handleFileRead(String);
public:
// Singleton Declarations
static WebServer* getInstance();
~WebServer() {instanceFlag = false;}
// Other Declarations
void initialize(int);
void handleLoop();
};
webserver.cpp:
#include "webserver.h"
bool WebServer::instanceFlag = false;
WebServer* WebServer::single = NULL;
WebServer* WebServer::getInstance() {
if(!instanceFlag) {
single = new WebServer();
instanceFlag = true;
return single;
} else {
return single;
}
}
void WebServer::initialize (int port) {
ESP8266WebServer server(port);
FS *filesystem;
filesystem->begin();
Serial.print("Open: http://");
Serial.print(WiFi.hostname().c_str());
Serial.println(".local");
server.onNotFound([]() {
if (!single->handleFileRead(single->server.uri())) {
single->server.send(404, "text/plain", "404: File not found.");
}
});
server.begin();
Serial.print("HTTP server started on port ");
Serial.print(port);
Serial.println(".");
}
String WebServer::getContentType(String filename) {
if (single->server.hasArg("download")) {
return "application/octet-stream";
} else if (filename.endsWith(".htm")) {
return "text/html";
} else if (filename.endsWith(".html")) {
return "text/html";
} else if (filename.endsWith(".css")) {
return "text/css";
} else if (filename.endsWith(".js")) {
return "application/javascript";
} else if (filename.endsWith(".png")) {
return "image/png";
} else if (filename.endsWith(".gif")) {
return "image/gif";
} else if (filename.endsWith(".jpg")) {
return "image/jpeg";
} else if (filename.endsWith(".ico")) {
return "image/x-icon";
} else if (filename.endsWith(".xml")) {
return "text/xml";
} else if (filename.endsWith(".pdf")) {
return "application/x-pdf";
} else if (filename.endsWith(".zip")) {
return "application/x-zip";
} else if (filename.endsWith(".gz")) {
return "application/x-gzip";
} else {
return "text/plain";
}
}
bool WebServer::handleFileRead(String path) {
Serial.println("handleFileRead: " + path);
if (path.endsWith("/")) {
path += "index.htm";
}
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if (filesystem->exists(pathWithGz) || filesystem->exists(path)) {
if (filesystem->exists(pathWithGz)) {
path += ".gz";
}
File file = filesystem->open(path, "r");
single->server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
void WebServer::handleLoop() {
single->server.handleClient();
}
The errors I am getting are all similar to the following:
src\webserver.cpp: In member function 'bool WebServer::handleFileRead(String)':
src\webserver.cpp:81:23: error: 'WebServer::single->WebServer::server' does not have class type
single->server.streamFile(file, contentType);
I get the idea of "does not have a class type", I just have no idea what it means here. In my mind, "single" is a pointer to the class so I'm unclear what that reference is not working.
Obviously, there are ample examples out there how to do a web server without encapsulating it. Other things I need to do for this project lend itself to creating that requirement.
There are some mistake in your code.
In webserver.h:
...
private:
// Singleton Declarations
static bool instanceFlag;
static WebServer *single;
WebServer() {}
// Other Declarations
FS *filesystem;
ESP8266WebServer *server; // <--- remove the parentheses and make it a pointer
String getContentType(String);
bool handleFileRead(String);
...
In webserver.cpp:
In WebServer::initialize I am guessing you want to initialize the class server and filesystem not locals, so it should probably look like this:
void WebServer::initialize (int port) {
server = new ESP8266WebServer(port);
filesystem = new FS();
...
}
And now everywhere you use the server you have to use the -> operator.
For example:
void WebServer::handleLoop() {
single->server->handleClient();
}
Please keep in mind that server and filesystem objects have to be deleted to avoid memory leaks.
EDIT:
You get the new error because FS has no constructor without arguments.
FS's constructor looks like this: FS(FSImplPtr impl) : _impl(impl) { }, here you can see that FSImplPtr is a typedef for std::shared_ptr<FileImpl>, so you need to provide this as a parameter.
It works your way, because SPIFFS's existence is declared here and is of type FS.
If you want to use SPIFFS, you have to use it like this: filesystem = &SPIFFS;, not like you mentioned in the comments (FS* filesystem = &SPIFFS;) because your way creates a new temporary variable named filesystem, and probably you expect to initiate the filesystem in the class, not a local one.

Header functions

EDIT: by not working I mean that in my main array mA in main doesn't show any change to the elements within the array.
I have been checking my functions as I develop the headers and they have been working perfectly: Until I got to the final header MonitorArray.h.
mA.getScreen(i).checkScreen();
Didn't work and I couldn't work out why. So I created a new function within MonitorArray to do a similar job using the same function, and to my surprise it worked.
mA.pollScreens();
Which uses (Inside MonitorArray.h):
monitorArray[i].checkScreen();
Function getScreen:
ScreenArray MonitorArray::getScreen(int arrayPointer)
{
if (arrayPointer<0 || arrayPointer>=monitors)
{
return false;
}
else
{
return monitorArray[arrayPointer];
}
}
Function checkScreen and addArray:
void ScreenArray::checkScreen()
{
HDC dMonitor;
PixelArray pArray;
int lenX = 0, lenY = 0;
dMonitor = CreateDC(iMonitor.szDevice, iMonitor.szDevice, NULL, NULL);
lenX = (iMonitor.rcWork.right - iMonitor.rcWork.left) - 1;
lenY = (iMonitor.rcWork.bottom - iMonitor.rcWork.top) - 1;
pArray.setColour(0, GetPixel(dMonitor, 0, 0));
pArray...
...
...
addArray(&pArray);
ReleaseDC(NULL, dMonitor);
}
void ScreenArray::addArray(PixelArray* pA)
{
if (previousCheck(*pA))
{
arrayPosition = 0;
screenArray[arrayPosition] = *pA;
arrayPosition++;
}
else
{
screenArray[arrayPosition] = *pA;
arrayPosition++;
}
if (arrayPosition==11)
{
//Run screen saver on monitor
}
}
Why does running the command within the header file through a new function work but running the functions from main not?
Assuming that "didn't work" means "didn't affect the ScreenArray in my MonitorArray", it's because getScreen returns a copy of the array element
ScreenArray MonitorArray::getScreen(int arrayPointer)
while the new member function most likely works with the array directly.
You'll need to return a pointer to the array element instead:
ScreenArray* MonitorArray::getScreen(int arrayPointer)
{
if (arrayPointer<0 || arrayPointer>=monitors)
{
return NULL;
}
else
{
return &monitorArray[arrayPointer];
}
}
(BTW: the implicit conversion from bool to ScreenArray looks very odd.)

Execute a piece of code in a function from the second invocation onwards

If I desire to run a piece of code in a function, only from the second invocation of the function onwards,
Questions:
Is there something wrong to do that?
How can I possibly achieve this ? Is using a static variable to do this a good idea ?
There's two answers to this question, depending on whether you have to deal with multi-threaded serialization or not.
No threading:
void doSomething() {
static bool firstTime = true;
if (firstTime) {
// do code specific to first pass
firstTime = false;
} else {
// do code specific to 2nd+ pass
}
// do any code that is common
}
With threading:
I'll write the generic boilerplate, but this code is system specific (requiring some variant of an atomic compareAndSet).
void doSomethingThreadSafe() {
static volatile atomic<int> passState = 0;
do {
if ( passState == 2 ) {
//perform pass 2+ code
break;
} else
if ( passState.compareAndSet(0,1) ) { // if passState==0 set passState=1 return true else return false
//perform pass 1 initialization code
passState = 2;
break;
} else {
//loser in setup collision, delay (wait for init code to finish) then retry
sleep(1);
}
} while(1);
//perform code common to all passes
}
Multi-threading will be a problem. To prevent this, if required, you'll probably need something like a mutex.
Like this:
void someFunction()
{
static bool firstRun = true;
if (!firstRun)
{
// code to execute from the second time onwards
}
else
{
firstRun = false;
}
// other code
}
Add a global counter.
eg:-
static int counter = 0;
public void testFunc(){
if(counter==1){
........
<Execute the functionality>
........
}
counter++;
}

How can I find the depth of a recursive function in C++

How can I find the current depth inside a recursive function in C++ without passing in the previous level? i.e. is it possible to know how many times the function was called without using a parameter to keep track of the level and passing that number in as a parameter each time the function is called?
For example my recursive function looks like this:
DoSomething(int level)
{
print level;
if (level > 10)
return;
DoSomething(++level);
}
main
{
DoSomething(0);
}
Building on the answer already given by JoshD:
void recursive()
{
static int calls = 0;
static int max_calls = 0;
calls++;
if (calls > max_calls)
max_calls = calls;
recursive();
calls--;
}
This resets the counter after the recursive function is complete, but still tracks the maximum depth of the recursion.
I wouldn't use static variables like this for anything but a quick test, to be deleted soon after. If you really need to track this on an ongoing basis there are better methods.
You could use a static variable in the function...
void recursive()
{
static int calls = 0;
calls++;
recursive();
}
Of course, this will keep counting when you start a new originating call....
If you want it to be re-entrant and thread-safe, why not:
void rec(int &level) // reference to your level var
{
// do work
rec(++level); // go down one level
}
main()
{
//and you call it like
int level=0;
rec(level);
cout<<level<<" levels."<<endl;
}
No static/global variables to mess up threading and you can use different variables for different recursive chains for re-entrancy issues.
You can use a local static variable, if you don't care about thread-safety.
Although, this will only give you a proper count the first time you run your recursive routine. A better technique would be a RAII guard-type class which contains an internal static variable. At the start of the recursive routine, construct the guard class. The constructor would increment the internal static variable, and the destructor would decrement it. This way, when you create a new stack-frame the counter increments by one, and when you return from each stack-frame the counter would decrement by one.
struct recursion_guard
{
recursion_guard() { ++counter; }
~recursion_guard() { --counter; }
static int counter;
};
int recursion_guard::counter = 0;
void recurse(int x)
{
recursion_guard rg;
if (x > 10) return;
recurse(x + 1);
}
int main()
{
recurse(0);
recurse(0);
}
Note however, that this is still not thread-safe. If you need thread-safety, you can replace the static-storage variable with a thread-local-storage variable, either using boost::thread_specific_ptr or the C++0x thread local facilities.
You could also pass in the level as a template parameter, if it can be determined at compile-time. You could also use a function object. This is by far and away the best option - less hassle, and static variables should be avoided wherever possible.
struct DoSomething {
DoSomething() {
calls = 0;
}
void operator()() {
std::cout << calls;
calls++;
if (calls < 10)
return operator()();
return;
}
int calls;
};
int main() {
DoSomething()(); // note the double ().
std::cin.get();
}
convert level to an instance variable of a new object (typically a template) capable of containing the arguments and (possibly) the function. then you can reuse the recursion accumulator interface.
You can also try using a global variable to log the depth.
var depth = 0;
DoSomething()
{
print ++depth;
if (depth > 10)
return;
DoSomething();
}
main
{
DoSomething(0);
}
I came here when I sensed that some recursion is required, because I was implementing a function that can validate the chain of trust in a certificate chain. This is not X.509 but instead it is just the basics wherein the issuer key of a certificate must match the public key of the signer.
bool verify_chain(std::vector<Cert>& chain,
Cert* certificate,
unsigned char* pOrigin = nullptr, int depth = 0)
{
bool flag = false;
if (certificate == nullptr) {
// use first element in case parameter is null
certificate = &chain[0];
}
if (pOrigin == nullptr) {
pOrigin = certificate->pubkey;
} else {
if (std::memcmp(pOrigin, certificate->pubkey, 32) == 0) {
return false; // detected circular chain
}
}
if (certificate->hasValidSignature()) {
if (!certificate->isRootCA()) {
Cert* issuerCert = certificate->getIssuer(chain);
if (issuerCert) {
flag = verify_chain(chain, issuerCert, pOrigin, depth+1);
}
} else {
flag = true;
}
}
if (pOrigin && depth == 1) {
pOrigin = nullptr;
}
return flag;
}
I needed to know the recursion depth so that I can correctly clean up pOrigin. at the right stack frame during the unwinding of the call stack.
I used pOrigin to detect a circular chain, without which the recursive call can go on forever. For example,
cert0 signs cert1
cert1 signs cert2
cert2 signs cert0
I later realized that a simple for-loop can do it for simple cases when there is only one common chain.
bool verify_chain2(std::vector<Cert> &chain, Cert& cert)
{
Cert *pCert = &cert;
unsigned char *startkey = cert.pubkey;
while (pCert != nullptr) {
if (pCert->hasValidSignature()) {
if (!pCert->isRootCA()) {
pCert = pCert->getIssuer(chain);
if (pCert == nullptr
|| std::memcmp(pCert->pubkey, startkey, 32) == 0) {
return false;
}
continue;
} else {
return true;
}
} else {
return false;
}
}
return false;
}
But recursion is a must when there is not one common chain but instead the chain is within each certificate. I welcome any comments. Thank you.