I create an object and try to pass that object through multiple function by reference
#include<iostream>
#include <string>
#include "DBMS.h"
using namespace std;
void Home(DBMS &);
int main()
{
DBMS dbms();
Home(dbms); // this is where the error is
return 0;
}
void Home(DBMS &dbms)
{
string dbName;
dbms.addDatabase(dbName);
}
and this is DBMS.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "Database.h"
using namespace std;
class DBMS
{
public:
DBMS();
void addDatabase(string);
Database& getDatabase(string);
Database& getDatabaseByIndex(int);
int getDatabaseIndex(string);
void removeDatabase(string);
int size();
~DBMS();
private:
vector <Database> dbList;
string error;
};
DBMS::DBMS()
{
}
void DBMS::addDatabase(string tbNames)
{
vector<string> TB_Names = tokenize(tbNames);
int size = TB_Names.size();
for (int i = 0; i < size; i++)
{
if (getDatabaseIndex(TB_Names[i]) == -1)
{
Database tb(TB_Names[i]);
dbList.push_back(tb);
}
else
throw "Already esited Database with given name";
}
}
Database& DBMS::getDatabase(string tbName)
{
int i;
int size = dbList.size();
for (i = 0; i < size; i++)
{
if (dbList[i].getName() == tbName)
return dbList[i];
}
throw invalid_argument("Database not found");
}
Database& DBMS::getDatabaseByIndex(int index)
{
return dbList[index];
}
void DBMS::removeDatabase(string TB_Name)
{
int i;
int size = dbList.size();
for (i = 0; i < size; i++)
{
if (dbList[i].getName() == TB_Name)
{
dbList.erase(dbList.begin() + i);
break;
}
}
if (i == size)
throw invalid_argument("Field not found");
}
int DBMS::getDatabaseIndex(string TB_Name)
{
int size = dbList.size();
for (int i = 0; i < size; i++)
{
if (dbList[i].getName() == TB_Name)
return i;
}
return -1;
}
int DBMS::size()
{
return dbList.size();
}
DBMS::~DBMS()
{
}
(Database type is just another class i create. Nothing special about it. Don't worry about it (Unless you think I have to))
The error statement is : >a reference of type "DBMS &" (a non-const-qualified) cannot be initialized with an value of "DBMS()"
I found a suggestion that i should fix void Home(DBMS &dbms) to void Home(const DBMS &dbms)
but if i do that, i can't use addDatabase() function
How can i fix this?
This declaration
DBMS dbms();
is a vexing parse. You are not declaring a variable named dbms, but instead you are actually declaring a function named dbms that takes no arguments, and returns a DBMS. Passing this object to a function expecting a DBMS object will not work.
You can fix this with:
DBMS dbms{};
What is the best way to end the lifetime of an object with static storage duration?
Current implementation finds the caller of __run_exit_handlers which then will be used to determine the __exit_funcs.
However this would easily fail since offset to __run_exit_handlers can change easily even in glibc with the same version. Another thing that could be done is to resolve the address of __run_exit_handlers first then use it in finding the caller rather than using a hardcoded call offset.
Current Working Code:
#include <iostream>
#include <fstream>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cstdio>
#include <execinfo.h>
struct A
{
A(std::string pName)
: mName(pName)
{
std::printf("%s %s\n", __PRETTY_FUNCTION__, mName.c_str());
}
~A()
{
std::printf("%s %s\n", __PRETTY_FUNCTION__, mName.c_str());
}
volatile int i = 0;
std::string mName;
};
A a{"a"};
A b{"b"};
A c{"c"};
class StaticDestroyer
{
public:
StaticDestroyer()
{
std::ifstream maps("/proc/self/maps", std::ios::in);
char line[1024];
uint8_t* magic = nullptr;
while (maps.getline(line, sizeof(line)))
{
char perms[4];
uint8_t *magicbegin, *magicend;
std::string lsv(line);
if (std::string::npos == lsv.find("/libc-",0,6)) continue;
std::sscanf(line, "%lx-%lx %4s", &magicbegin, &magicend, perms);
if (perms[0]==114 && perms[2]==120)
{
magic = findMagic(magicbegin, magicend);
break;
}
}
if (magic==nullptr)
throw std::runtime_error("magic not found!");
mHead = *(HakaishinNode**)magic;
}
bool destroy(void* pTarget)
{
HakaishinNode *current = mHead;
while (nullptr != current)
{
for (size_t i = current->idx-1 ; i>0; i--)
{
const Hakaishin *const f = ¤t->fns[i];
if (4 == f->type && pTarget == f->arg)
{
void (*destruct) (void *arg, int status) = f->fn;
asm ("ror $2*8+1, %0\nxor %%fs:%c2, %0" : "=r" (destruct) : "0" (destruct), "i" (48));
destruct (f->arg, 1);
if (current->idx-1 != i) for (size_t j = i; j < current->idx ; j++) current->fns[j] = current->fns[j+1];
current->idx--;
return true;
}
}
current = current->next;
}
return false;
}
private:
struct Hakaishin
{
long int type;
void (*fn) (void *arg, int status);
void *arg;
void *dso_handle;
};
struct HakaishinNode
{
struct HakaishinNode *next;
size_t idx;
Hakaishin fns[32];
};
uint8_t* findMagic(uint8_t* magicbegin, uint8_t* magicend)
{
const void* const begin = magicbegin;
int32_t ptr;
while ((magicbegin+7) <= magicend)
{
if (magicbegin[0]==0x48 && (magicbegin[1]==0x8b || magicbegin[1]==0x8d))
{
std::memcpy(&ptr, magicbegin+3, sizeof(ptr));
uint8_t* magicp = magicbegin+ptr+7;
if (ptr==0x38a5c1) return magicp;
}
magicbegin++;
}
return nullptr;
}
HakaishinNode* mHead = nullptr;
};
A& getA()
{
static A a{"getA"};
return a;
}
A& getA2()
{
static A a{"getA2"};
return a;
}
int main()
{
std::printf("entering...\n");
StaticDestroyer d;
d.destroy(&a);
d.destroy(&b);
auto& ga = getA();
d.destroy(&ga);
getA2();
std::printf("returning...\n");
}
Output:
A::A(std::string) a
A::A(std::string) b
A::A(std::string) c
entering...
A::~A() a
A::~A() b
A::A(std::string) getA
A::~A() getA
A::A(std::string) getA2
returning...
A::~A() getA2
A::~A() c
Static objects will be destructed with the termination of the program.
If you like to manage the resources don't make it static or use a static pointer. Here you can allocate and de-allocate the corresponding resources. This approach comes very close to a singleton, which is considered to be an anti pattern.
Conclusion:
If you need to manage a resource don't make it static.
The need to mess around with the default behavior of life-time in such a way indicates that you have a design flaw in your application.
So you should either consider restructuring your program to not use globals. Or at least change the way how you handle the globals. So if you really need globals and release them earlier, then switch to unique_ptr:
#include <iostream>
#include <functional>
#include <memory>
struct A
{
A(std::string pName)
: mName(pName)
{
std::printf("%s %s\n", __PRETTY_FUNCTION__, mName.c_str());
}
~A()
{
std::printf("%s %s\n", __PRETTY_FUNCTION__, mName.c_str());
}
volatile int i = 0;
std::string mName;
};
auto a = std::make_unique<A>("a");
auto b = std::make_unique<A>("b");
auto c = std::make_unique<A>("c");
auto& getA()
{
static auto a = std::make_unique<A>("getA");
return a;
}
auto& getA2()
{
static auto a = std::make_unique<A>("getA2");
return a;
}
int main() {
std::printf("entering...\n");
a = nullptr;
b = nullptr;
c = nullptr;
getA();
getA2();
getA() = nullptr;
std::printf("returning...\n");
}
That way you can release the objects managed by the unique_ptr earlier, but they will be released on exit automatically if you don't set them to nullptr manually.
my type aButton has a function pointer so i can define custom actions for each button, i though the easiest way to do this would be to create a lambda and dereference it and pass it to the function pointer of that aButton instance, since i need non-static access to objects outside of the scope of the button class
but i'm stuck trying to figure out how to cast it to the right type and how to call it without getting the errors below... i haven't see many people have luck with this, and using functional doesn't look like i can pass in context???
// Example program
#include <iostream>
#include <string>
int global1 = 0;
int global2 = 5;
class aButton {
public:
int status, oldStatus;
aButton(int initStatus) { oldStatus = status = initStatus; }
int (aButton::*action)();
};
class Thingy {
private:
int mode = 1;
int value = 0;
public:
void reset() { value = 0; }
void setMode(int newMode) { mode = newMode; }
void increment() { value = value + global2; }
//accessors & mutators
};
void specialFunction(Thingy *thingyToWorkOn) {
//do stuff...
}
void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
//more stuff...
}
int main() {
Thingy one;
Thingy two;
aButton *on = new aButton(0);
aButton *speedUp = new aButton(0);
on->action = &( //error: taking address of temporary [-fpermissive]
[&]() { //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment
//some specific stuff....
global1 = 1;
if (global2 < 10) {
global2++;
}
one.reset();
two.reset();
anotherSpecialFunction(&one, &two);
std::cout << "on action \n";
return 1;
}
);
speedUp->action = &( //error: taking address of temporary [-fpermissive]
[&]() { //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment
//some specific stuff....
if (global1) {
one.setMode(global2);
two.setMode(global2);
specialFunction(&one);
specialFunction(&two);
std::cout << "speedUp action \n";
return 1;
}
return 0;
}
);
for(int i=0; i<5; i++) {
//if on pushed
(on->(on->action))(); //error: expected unqualified-id before '(
//if speedUp pushed
(speedUp->(speedUp->action))(); //error: expected unqualified-id before '(
}
}
I believe that you want aButton::action to be of type std::function<int()> (read: function that takes nothing and returns int) rather than int (aButton::*). This requires the <functional> header. With that change, your assignments could stay the same (minus the leading address-of operator), though as you figured out, you'll need to explicitly state the return type with -> int. The calls would simply take the form (e.g.):
on->action();
One other note: be very careful about capturing local variables (one, two) by reference. If the function really is main then I suppose it's ok since main won't return until the program ends, but otherwise it would be asking for trouble.
You cannot assign pointer to lambda to pointer to member function. Pointers to member functions may point only to member functions.
You can indeed use std::function from <functional> instead. Declare your action as
std::function<int()> action;
so instead of using member functions you will use global functions. Of course you need to get rid of & operators for lambdas. And you need to modify the way of calling action.
Thanks guys, i guess functional was what i was looking for after all... this seems to do what i want on http://cpp.sh/8ll i guess i just got confused cause a lot of the functional examples had them as arguments for callbacks instead
// Example program
#include <iostream>
#include <string>
#include <functional>
int global1 = 0;
int global2 = 5;
class aButton {
public:
int status, oldStatus;
aButton(int initStatus) { oldStatus = status = initStatus; }
std::function<int()> action;
};
class Thingy {
private:
int mode = 1;
int value = 0;
public:
void reset() { value = 0; }
void setMode(int newMode) { mode = newMode; }
void increment() { value = value + global2; }
//...
};
void specialFunction(Thingy *thingyToWorkOn) {
//do stuff...
}
void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
//more stuff...
}
int main() {
Thingy one;
Thingy two;
aButton *on = new aButton(0);
aButton *speedUp = new aButton(0);
on->action = std::function<int()>(
[&]() -> int{
//some specific stuff....
global1 = 1;
if (global2 < 10) {
global2++;
}
one.reset();
two.reset();
anotherSpecialFunction(&one, &two);
std::cout << "on action \n";
return 1;
}
);
speedUp->action = std::function<int()>(
[&]() -> int{
//some specific stuff....
if (global1) {
one.setMode(global2);
two.setMode(global2);
specialFunction(&one);
specialFunction(&two);
std::cout << "speedUp action \n";
return 1;
}
return 0;
}
);
for(int i=0; i<5; i++) {
//if on pushed
on->action();
//if speedUp pushed
speedUp->action();
}
}
I've been looking around and haven't come up with any tangible solutions. It sounds like it is looking for a default constructor instead of the one in place but I have one below. Moving it up as the first listed constructor didn't change the error messages so I'm wrong about that. Here's the full error message (using jGRASP):
In file included from intset.h:47:0,
from IntSet.cpp:1:
IntSet.cpp:12:11: error: expected unqualified-id before 'int'
IntSet(int a, int b, int c, int d, int e) {
^
IntSet.cpp:12:11: error: expected ')' before 'int'
Here's the IntSet.cpp code:
#include "intset.h"
//#include <algorithm>
//#include <iostream>
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
//Constructors
IntSet(int a, int b, int c, int d, int e) {
size = a;
if(b > size) {
size = b;
}
if(c > size) {
size = c;
}
if(d > size) {
size = d;
}
if(e > size) {
size = e;
}
set = new bool[size];
for(int i = 0; i <= size; i++) {
if(i == a || i == b || i == c || i == d || i == e) {
insert(i);
} else {
remove(i);
}
}
}
IntSet(int a, int b, int c, int d) {
IntSet(a, b, c, d, -1);
}
IntSet(int a, int b, int c) {
IntSet(a, b, c, -1, -1);
}
IntSet(int a, int b) {
IntSet(a, b, -1, -1, -1);
}
IntSet(int a) {
IntSet(a, -1, -1, -1, -1);
}
//Copy constructor
IntSet(const IntSet& x) {
size = x.size;
for (int i = 0; i <= x.size; i++ ) {
set[i] = x.set[i];
}
}
//Destructor
~IntSet()
{
//for(int i = this.length(); i >= 0; i--) {
// this[i]
//}
}
////////////////////////
bool insert(int a) {
if(a <= size && a >= 0) {
set[a] = true;
return true;
}
else if(a >= 0) {
//removed "new" from line below
IntSet temp = IntSet(a);
&this += temp;
set[a] = true;
return true;
}
return false;
}
bool remove (int a) {
if (isInSet(a)) {
set[a] = false;
return true;
}
return false;
}
bool isEmpty() {
bool retVal = true;
for (int i = 0; i <= size; i++) {
if (set[i] == true) {
retVal = false;
}
}
return retVal;
}
bool isInSet (int a) {
if (set[a]){
return true;
}
return false;
}
/////////////////////////////////////////////
IntSet operator + (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] || a.set[i]){
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator * (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] && a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator - (IntSet a) {
IntSet c = IntSet();
c.size = 0;
for (int i = 0; i <= size; i++) {
if (set[i] && !a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
c.size++;
}
return c;
}
IntSet operator = (const IntSet a) {
return IntSet(a);
}
IntSet operator += (IntSet a) {
return IntSet(operator+(a));
}
IntSet operator *= (IntSet a) {
return IntSet(operator * (a));
}
IntSet operator -= (IntSet a) {
return IntSet(operator - (a));
}
IntSet operator == (const IntSet a) const{
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return false;
}
}
return true;
}
IntSet operator != (IntSet a) {
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return true;
}
}
return false;
}
IntSet operator << (IntSet a) {
cout << "{";
for(int i = 0; i < size; i++) {
if(set[i]) {
cout << " " << i;
}
}
cout << "}";
}
IntSet operator >> (IntSet a) {
int index;
while(cin >> index && index != SENTINEL) {
insert(index);
}
}
Here is the attached intset.h code:
#ifndef INTSET_H
#define INTSET_H
#include <iostream>
#include <algorithm>
using namespace std;
class IntSet {
public:
//Constructors
IntSet();
IntSet(int);
IntSet(int, int);
IntSet(int, int, int);
IntSet(int, int, int, int);
IntSet(int, int, int, int, int);
IntSet(const IntSet&); // M: Added the &; must be a pointer or reference
~IntSet();
//Overloaded Operators M: Added 'IntSet' in front of the word 'operator.'
// It was required syntax.
IntSet operator+(IntSet);
IntSet operator*(IntSet);
IntSet operator-(IntSet);
IntSet operator=(IntSet);
IntSet operator+=(IntSet);
IntSet operator*=(IntSet);
IntSet operator-=(IntSet);
IntSet operator==(IntSet);
IntSet operator!=(IntSet);
IntSet operator<<(IntSet);
IntSet operator>>(IntSet);
//Functions
bool insert(int);
bool remove(int);
bool isEmpty();
bool isInSet(int);
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
#include "IntSet.cpp"
#endif
I haven't had much experience with header files so it wouldn't surprise me if I formatted something incorrectly but I'm looking at plenty of other samples provided by the professor and there isn't anything unusual about mine. I thought maybe it had something to do with the order listed in the .h file and that I wasn't following the same exact order in the .cpp but nothing changed when I had everything listed in the same order.
There is a lot that is wrong with your code. We are going to have to jump around a bit between the header and the implementation. Ready?
In your header you do this:
class IntSet {
/* stuff */
private:
bool set[];
};
First of all, the name set is a bad choice: it is the name of a class in namespace stdw which you are importing by having using namespace std in your header file. This can be confusing at best.
More importantly, the syntax bool set[] isn't correct in this context. Even if your compiler allows it, it's an extension. Who knows what it does and how it will behave on other compilers? Avoid it.
If you want to declare an array, declare an array. If you want to declare a pointer, declare a pointer. Just remember: an array isn't a pointer.
Unfortunately you don't, becase later on in your code you do this:
set = new bool[size];
What is this supposed to do? set isn't a pointer, it's some kind of array, and you cannot assign a pointer to an array.
Now, we get to the second problem: you declare some member variables for your class, in your header file:
class IntSet {
/* some stuff here */
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
Then in your implementation you have the following code floating up at the top:
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
I don't think that this does what you think it does. It seems that your intention is to initialize those variables, but that's not what happens. Remember, those variables only exist as members variables that belong to a particular instance of a class, and they are not "free-standing". So what's happening here?
Well, this declares all these variables again, so you have variables called MAXSIZE, size, set and SENTINEL that are valid anywhere in that translation unit (i.e. the .cpp file), independent of the member variables in the class.
This, of course, means that the member variables with those names aren't initialized (well, except set which you assign a pointer to, which we already know is wrong). This will cause your code to exhibit undefined behavior. After all, the value of an uninitialized variable can be anything at all.
If your intention had been to initialize the class members, then you should remove that code and initialize those variables in your constructor(s):
IntSet::IntSet(int a, int b, int c, int d, int e)
: size(a), MAXSIZE(25000), SENTINEL(-1)
{
/* whatever*/
}
Notice, by the way, how I used IntSet:: in front of the constructor name? This is called the scope resolution operator. Remember, there is no constructor called IntSet. The constructor belongs to a class, which is called IntSet, and outside of that class, it's proper name is IntSet::IntSet. A small example may help:
class Test
{
int Length;
public:
/* notice how inside the class, you only need Test
* when providing a body for the constructor. This
* makes sense. You know which class you inside of.
*/
Test()
: Length(0)
{
}
Test(int len);
};
/* Now we are outside the class. We need to help
* the compiler out and tell it what class the
* function belongs to.
*/
Test::Test(int len)
: Length(len)
{
}
A tangential point as to do with the names that you are using. What's a? Why do you use a to initialize something called size? You should choose meaningful variables names that help document the code so that when you have to read it back your head doesn't explode.
Another tangential point is that if variables like MAXSIZE and SENTINEL are going to be shared between all instances of the class, then, for future reference, you should probably consider making them static class members.
Lastly, you have this bit of code in your header file
#include "IntSet.cpp"
This is, almost certainly, not correct. You should never do this (there may be some who think that there are exceptions, but don't learn bad habits at this point. When you know enough to stumble on this legitimately, then you will know enough to determine whether it's the right thing to do or not).
What makes it worse is that your implementation file contains:
#include "IntSet.h"
Think about what you are doing here: when the compiler is processing the file IntSet.h you are telling to also process the file IntSet.cpp. The file IntSet.cpp tells the compiler to process the file IntSet.h. Which tells the compiler to process the file IntSet.cpp. And so on and so forth.
Generally speaking, implementation files (.cpp) will include header files. Header files will only include other header files.
There are a few other issues, but you should probably fix all these things, and then, if you are still having issues, post a new question and we can go from there.
Good luck!
You need to put the name of the class and :: before defining a member function.
IntSet::IntSet(int a, int b, int c, int d, int e) {
//^^^^^^^^
//here
Do the same with the other constructors, the operators and methods.
I'm getting a weird problem in memory deallocation.
I have the following code for class MemoryPartition:
#include <cstring>
#include <iostream>
#include "memorypartition.h"
MemoryPartition::MemoryPartition(int maxSize) {
this->partitionArray = new char[maxSize];
memset(this->partitionArray, ((int) '$'), maxSize);
this->maxSize = maxSize;
this->isFree = true;
}
MemoryPartition::~MemoryPartition() {
delete[] this->partitionArray;
this->partitionArray = NULL;
maxSize = 0;
}
void MemoryPartition::setFree(bool isFree) {
this->isFree = isFree;
}
bool MemoryPartition::getFree() {
return this->isFree;
}
int MemoryPartition::getMaxSize() {
return this->maxSize;
}
void MemoryPartition::getPartitionArray() {
for(int i = 0;i < maxSize;i++) {
std::cout << partitionArray[i] << ' ';
}
std::cout << std::endl;
}
and the following code for MemoryManager:
#include "memorymanager.h"
#include <iostream>
#include <cstdlib>
MemoryManager::MemoryManager() {
}
MemoryManager::~MemoryManager() {
memory.clear();
}
void MemoryManager::defmem(int bytes) {
MemoryPartition *memPartition;
int maxMemorySize = bytes;
while(maxMemorySize != 0) {
int partitionSize = this->randomPartitionSize(maxMemorySize);
memPartition = new MemoryPartition(partitionSize);
this->memory.push_back(*memPartition);
std::cout << memPartition->getMaxSize() << std::endl;
memPartition->getPartitionArray();
maxMemorySize -= partitionSize;
delete memPartition;
memPartition = NULL;
}
}
int MemoryManager::randomPartitionSize(int maxSize) {
int value;
srand(time(NULL));
value = (rand() % maxSize) + 1;
return value;
}
and I'm getting a weird at delete[] in MemoryPartition destructor. Valgrind is telling me there are 13 frees and 10 allocs, but I can't see a reason why this delete[] would be called 3x.
Anyone see the problem I couldn't figure out?
Thanks in advance.
[]'s,
Its impossible to tell from the code above.
But my guess is that you need to define the copy constructor and assignment operator.
See Rule of 4 (Google/Wiki it).
Try the following:
class MemoryPartition
{
// Just add these two lines (keep them private)
MemoryPartition(MemoryPartition const&); // Don't define.
MemoryPartition& operator=(MemoryPartition const&); // Don't define.
<CLASS STUFF AS BEFORE>
};
Compile the code now. If it fails because the above are private then you have accidentally made a copy of the object somewhere and are doing a double delete on the pointer.