So my code compiles well, but whenever I try running the program, it seg faults. I ran it through gdb and got this set of error:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Program received signal SIGABRT, Aborted.
0x00007ffff722bcc9 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
Here is my code if it helps:
using namespace std;
#include <iostream>
#include <vector>
#include <cmath>
#include<fstream>
#include <cstdlib>
#include <utility>
#include <string>
class Page
{
public:
int TimeStamp;
int ProgramOwner;
int LocalPageNumber;
};
//Pair: first entry is local page, second entry is global page
//Second entry: 1 if in main memory, 0 if not
class Program
{
public:
vector< pair<int,int> > MemoryMap;
};
class Memory
{
public:
vector<Program> Programs;
vector<Page> Pages;
};
void checkArguments(int argc, char *argv[]);
bool checkPageAlgorithm(char *argv[]);
bool checkPageSize(int pagesize);
bool checkPageStyle(char *argv[]);
bool checkPTrace(string ProgramTraceFile);
bool checkPList(string ProgramListFile);
int main(int argc, char *argv[])
{
//checkArguments(argc, argv);
const int MemSize = 512;
int pageSize = atoi(argv[3]);
string programListFile = argv[1];
string ProgramTraceFile = argv[2];
string pageAlgorithm = argv[4];
string pageStyle = argv[5];
int programNumber;
int programSize;
int PagesNeeded;
Memory MainMemory;
int numberFrames;
int pageFaults = 0;
int numPrograms = 0;
int PagesPerProgram;
int LocalPage;
int activeProgram;
int requestedLocation;
int newPageLocation;
bool foundInMemory;
ifstream fileIn;
fileIn.open(programListFile.c_str());
if(fileIn.fail())
{
cerr << "List file not found." << endl;
fileIn.close();
exit(1);
}
else
{
while(!fileIn.eof())
{
cout << "hey0";
fileIn >> programNumber;
fileIn >> programSize;
numPrograms++;
}
}
numberFrames = ceil(MemSize/pageSize);
PagesPerProgram = ceil(numberFrames/numPrograms);
MainMemory.Pages.resize(numberFrames);
cout << "hey1";
while(!fileIn.eof())
{
cout << "hey2";
fileIn >> programNumber;
fileIn >> programSize;
cout << "hey3";
PagesNeeded = ceil(programSize/pageSize);
for(int i = 0; i < PagesNeeded; i++)
{
LocalPage = i;
MainMemory.Pages[i].ProgramOwner = programNumber;
MainMemory.Pages[i].LocalPageNumber = LocalPage;
}
cout << "hey3";
if(PagesNeeded > PagesPerProgram)
PagesNeeded = PagesPerProgram;
for(int i = 0; i < PagesNeeded; i++)
{
MainMemory.Programs[programNumber].MemoryMap[i].first = MainMemory.Pages[i].LocalPageNumber;
MainMemory.Programs[programNumber].MemoryMap[i].second = 1;
if(pageAlgorithm == "clock")
MainMemory.Pages[i].TimeStamp = 1;
else
MainMemory.Pages[i].TimeStamp = 0;
}
}
fileIn.close();
//LRU Algorithm Implementation
if(pageAlgorithm == "lru")
{
cout << "here1";
fileIn.open(ProgramTraceFile.c_str());
if(fileIn.fail())
{
cerr << "That file does not exist." << endl;
fileIn.close();
exit(1);
}
else
{
fileIn >> activeProgram;
fileIn >> requestedLocation;
newPageLocation = ceil(requestedLocation/pageSize);
while(!fileIn.eof())
{
foundInMemory = false;
for(int i = 0; i < static_cast<int>(MainMemory.Programs[activeProgram].MemoryMap.size()); i++)
{
if((MainMemory.Programs[activeProgram].MemoryMap[i].second == 1) &&
(MainMemory.Programs[activeProgram].MemoryMap[i].first == newPageLocation))
foundInMemory = true;
if(foundInMemory)
break;
}
if(!foundInMemory)
{
pageFaults++;
if(static_cast<int>(MainMemory.Programs[activeProgram].MemoryMap.size()) < PagesPerProgram)
{
pair<int, int> temp;
temp.first = newPageLocation;
temp.second = 1;
MainMemory.Programs[activeProgram].MemoryMap.push_back(temp);
}
else
{
for(int i = 0; i < (static_cast<int>(MainMemory.Programs[activeProgram].MemoryMap.size()) - 1); i++)
{
if(MainMemory.Pages[i].TimeStamp >= MainMemory.Pages[i+1].TimeStamp)
{
MainMemory.Programs[activeProgram].MemoryMap[i].first = newPageLocation;
}
if(pageStyle == "1")
{
if(MainMemory.Pages[i].TimeStamp >= MainMemory.Pages[i+1].TimeStamp)
{
MainMemory.Programs[activeProgram].MemoryMap[i].first = MainMemory.Pages[i].LocalPageNumber;
}
}
MainMemory.Pages[i].TimeStamp++;
}
}
}
fileIn >> activeProgram;
fileIn >> requestedLocation;
newPageLocation = ceil(requestedLocation/pageSize);
}
}
}
cout << "------------------------------------" << endl;
cout << "Page Size: " << pageSize << endl;
cout << "Page Replacement Algorithm: " << pageAlgorithm << endl;
cout << "Paging Style: ";
if(pageStyle == "0")
cout << "Demand" << endl;
else
cout << "Prepaging" << endl;
cout << "Number of Page Faults: " << pageFaults << endl;
cout << "------------------------------------" << endl;
return 0;
}
bool checkPList(string programlistfile)
{
ifstream ListFile(programlistfile.c_str());
if(ListFile.fail())
{
cerr << "Cannot find file " << programlistfile << endl;
ListFile.close();
return false;
}
else
{
ListFile.close();
return true;
}
}
bool checkPTrace(string programTraceFile)
{
ifstream TraceFile;
TraceFile.open(programTraceFile.c_str());
if(TraceFile.fail())
{
cerr << "Cannot find file " << programTraceFile << endl;
TraceFile.close();
return false;
}
else
{
TraceFile.close();
return true;
}
}
bool checkPageStyle(string pageStyle)
{
if(pageStyle == "0")
return true;
else if(pageStyle == "1")
return true;
else
{
cerr << "Page Style can be: 0 or 1." << endl;
return false;
}
}
bool checkPageSize(int pagesize)
{
bool isValid = false;
switch(pagesize)
{
case 1:
isValid = true;
break;
case 2:
isValid = true;
break;
case 4:
isValid = true;
break;
case 8:
isValid = true;
break;
case 16:
isValid = true;
break;
default:
cerr << "Page Size can be: 1, 2, 4, 8, or 16." << endl;
isValid = false;
}
return isValid;
}
bool checkPageAlgorithm(string pageAlgorithm)
{
if(pageAlgorithm == "lru")
return true;
else if(pageAlgorithm == "fifo")
return true;
else if(pageAlgorithm == "clock")
return true;
else
{
cerr << "Valid Page Algorithms are: lru, fifo, or clock" << endl;
return false;
}
}
void checkArguments(int argc, char *argv[])
{
if(argc < 6)
{
cerr << "Invalid number of arguments. Should be: programlist programtrace pagesize pagealgorithm pagingstyle" << endl;
exit(1);
}
else if(argc > 6)
{
cerr << "Invalid number of arguments. Should be: programlist programtrace pagesize pagealgorithm pagingstyle" << endl;
exit(1);
}
else if(!checkPageAlgorithm(argv[4]))
exit(1);
else if(!checkPageSize(atoi(argv[3])))
exit(1);
else if(!checkPageStyle(argv[5]))
exit(1);
else if(!checkPTrace(argv[2]))
exit(1);
else if(!checkPList(argv[1]))
exit(1);
return;
}
The output 'heys' are just to see if they get triggered within gdb, which they don't.
You forgot to actually ask any question.
Presumably, your question is "why does my program die with SIGABRT?"
The answer was provided by the program itself: you've tried to construct std::string from a NULL character pointer, which throws std::logic_error exception (because it's not a valid thing to do).
You may have a follow-up quesiton: "where in my program does this happen?".
You could find the answer by using GDB where command. As a first guess, you didn't invoke your program with sufficient number of arguments. For example, if you did this:
gdb ./a.out
(gdb) run
then argv[1] is NULL, and this statement:
string programListFile = argv[1];
would throw the exception you are getting.
The common solution to this problem is to insist that you do have correct number of arguments, e.g. put this:
if (argc < 6) {
std::cerr << "Not enough arguments" << std::endl;
return 1;
}
at the start of main. Or just comment the call to checkArguments() back in.
Related
I'm having some trouble with an assignment that requires creating a hash table using a vector of Entry (ADT created by the professor). The program compiles successfully but gdb gives me the error message "No stack." when I try debugging. I've traced the error to a call to my function search() in my function insert().
I'm not sure where the problem comes from but I think it either stems from the way I access the vector or how I tried to initialize it in the constructor.
My source code is below, my professor wrote the structure Entry and class HT as well as the functions main() and hashing() which cannot be edited although new functions can be added to the class. Even though those parts cannot be edited I included them here for reference.
Here's my header file assignment8.h:
#ifndef ASSIGNMENT8_H
#define ASSIGNMENT8_H
#include <vector>
#include <string>
struct Entry {
std::string key;
std::string description;
Entry() { key = "---"; }
};
class HT {
private:
std::vector<Entry>* hTable;
int table_size=11;
int item_count;
int hashing(const std::string&);
public:
HT();
HT(int size);
~HT();
bool insert(const Entry& e);
int search(const std::string& key);
bool remove(const std::string& s);
void print();
//Student-made member fucntions
void setsize(int size){table_size = size;}
void setItemCount(int ic){ic = item_count;}
int getItemCount(){return item_count;}
};
#endif
and my cc file assignment8.cc:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "assignment8.h"
using namespace std;
Entry* get_entry(const string& line)
{
//Holder for string fragments
string strArr[3];
int index = 0;
//Split the string
for(unsigned int i = 0; i < line.length(); i++)
{
if(line[i] != ':')
strArr[index] += line[i];
else
index++;
}
Entry* newEntry = new Entry;
//Pass strings to newEntry
(*newEntry).key = strArr[1];
(*newEntry).description = strArr[2];
return newEntry;
}
string get_key(const string& line)
{
//Holder for string fragments
string strArr[2];
int index = 0;
//Split string
for(unsigned int i = 0; i < line.length(); i++)
{
if(line[i] != ':')
strArr[index] += line[i];
else
index++;
}
//Return item-key
return strArr[1];
}
//----HT----//
// key is in form of letter-letter-digit
// compute sum <-- ascii(pos1)+ascii(pos2)+ascii(pos3)
// compute sum%htable_size
int HT::hashing(const string& key) {
return ((int)key[0] + (int)key[1] + (int)key[2])%table_size;
}
//--Constructors
//Default Constructor
HT::HT(){}
//Constructor
HT::HT(int size)
{
//Initializations
if(!size)
size = 11;
setsize(size);
hTable = new vector<Entry>[table_size];
}
HT::~HT()
{
delete[] hTable;
}
int HT::search(const std::string& key)
{
//Look for unused slot
for(int i = 0; i < table_size; i++)
{
if((*hTable)[i].key == key)
return hashing(key);
}
return -1;
}
bool HT::insert(const Entry& e)
{
//Get e's key
string eKey = e.key;
//If it's full, print error message and return false
if(getItemCount() == table_size)
{
cout << "Hash table is full\n";
return false;
}
//Checks to see if key already exists
if(search(eKey) != -1)
{
cout << "Key already exists in table\n";
return false;
}
//If it does not already exist,
for(int i = 0; i < table_size; i++)
{
string iKey = (*hTable)[i].key;
cout << i << "iteration(s)"<< endl;
if(iKey == "---" || iKey == "+++")
{
//Compute hash key value and insert into position
(*hTable)[i] = e;
setItemCount(++item_count);
return true;
}
}
return false;
}
bool HT::remove(const std::string& s)
{
for(int i = 0; i < table_size; i++)
{
string iKey = (*hTable)[i].key;
if(iKey == s)
{
iKey = "+++";
setItemCount(--item_count);
return true;
}
}
return false;
}
void HT::print()
{
cout << "----Hash Table----" << endl;
for(int i = 0; i < table_size; i++)
{
cout << (*hTable)[i].key << " " << (*hTable)[i].description << endl;
}
cout << endl << "------------------" << endl;
}
int main(int argc, char** argv ) {
if ( argc < 2 ) {
cerr << "argument: file-name\n";
return 1;
}
HT ht;
ifstream infile(argv[1], ios::in);
string line;
infile >> line;
while ( !infile.eof() ) {
if ( line[0] == 'A' ) {
Entry* e = get_entry( line );
ht.insert( *e );
delete e;
}
else {
string key = get_key(line);
if ( line[0] == 'D' ) {
cout << "Removing " << key << "...\n";
bool removed = ht.remove( key );
if ( removed )
cout << key << " is removed successfully...\n\n";
else
cout << key << " does not exist, no key is removed...\n\n";
}
else if ( line[0] == 'S' ) {
int found = ht.search( key );
if ( found < 0 )
cout << key << " does not exist in the hash table ..." << endl << endl;
else
cout << key << " is found at table position " << found << endl << endl;
}
else if ( line[0] == 'P' ) {
cout << "\nDisplaying the table: " << endl;
ht.print();
}
else
cerr << "wrong input: " << line << endl;
}
infile >> line;
}
infile.close();
return 0;
}
Thank you for any help or advice! :)
main():
char inp[] = "(A+B)/(C*D))";
Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
Here is Infix constructor:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
Infix is inheriting from a class 'Stack':
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
When I run the code in main, it displays unusual output:
Element In Stack: (
Operator Array: /*-+%
In main: +%
Stack Object Destroyed!
But, when in main, if the comment the line declaring 'Infix' object declaration, the code runs fine:
In main: (A+B)/(C*D))
EDITS:
Stack Class
#include<iostream>
using namespace std;
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
bool Stack:: push(char elementToPush) {
if(top > 98) {
cout << "\nStack Overflow!!";
return false;
} else {
arr[++top] = elementToPush;
return true;
}
}
char Stack:: pop() {
if(top <= -1) {
cout << "\nStack Underflow!!";
return ' ';
} else {
return (arr[top--]);
}
}
char Stack:: peek() {
if(top > 98) {
cout << "\nStack Overflow!!";
return ' ';
} else {
return arr[top];
}
}
bool Stack:: isEmpty() {
return (top <= 0);
}
void Stack:: displayAll() {
if(top <= -1) {
cout << "null";
return;
}
int i = top;
while (i >= 0) {
cout << arr[i] << " ";
--i;
}
cout << "\n";
}
Infix Class
#include<iostream>
#include<cstring>
#include<D:\Programs\11Stack.cpp>
using namespace std;
class Infix : public Stack {
string outputString;
char operatorArray[];
public:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
string infixToPostfix(char *, int);
bool manupulateOperator(char, int);
int checkPrecedence(char);
~Infix() {
cout << "\nStack Object Destroyed!" << endl;
}
};
string Infix:: infixToPostfix(char *str, int size) {
cout << "\nGiven String: " << str << endl;
int x;
for(int i = 0; i < size; ++size) {
x = str[i];
if(x != ' ') {
if(x == ')') {
while(returnTop() != '(') {
cout << pop() << " popped!\n";
}
cout << pop() << " popped!\n";
} else if(isalpha(x)) {
cout << x;
} /* else{ // scanned character is an operator
if(manupulateOperator(x, i)) {
} else {
return " ";
}
} */
}
}
return outputString;
}
bool Infix::manupulateOperator(char c, int position) {
try {
char topElement = *returnElement(returnTop());
if(checkPrecedence(c) == -1) {
cout << "\nErr\n";
}else if((checkPrecedence(c) > checkPrecedence(topElement)) || returnTop() == 0) {
push(c);
cout << c << " pushed!\n";
}
} catch(std::exception e) {
std::cerr << e.what() << '\n';
return false;
} catch (char* Ce) {
cout << Ce << endl;
}
return true;
}
int Infix::checkPrecedence(char c) {
/*
+ -> 1
- -> 1
* -> 2
/ -> 2
% -> 2
*/
switch(c) {
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '/':
return 2;
case '%':
return 2;
default:
// throw "Illegal Operator Detected!";
cout << "Illegal Operator Detected: " << c << endl;
return -1;
}
}
int main() {
cout << endl;
int x = 1;
char inp[] = "(A+B)/(C*D))";
//Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
// cout << i.infixToPostfix(input + ')', sizeof(input));
/* for(int i = 0; i < strlen(inp); ++i) {
cout << inp[i];
}
*/
return 0;
}
You are declaring operatorArray as an array of char but you are not assigning any memory for it! So, when you then call strcpy(operatorArray, "/*-+%"); in your Infix constructor, you are causing undefined behaviour by attempting to copy the given string constant to memory that hasn't been assigned - and this appears to be overwriting the inp[] array declared in your main.
To fix this, I would suggest giving your operatorArray member a specific size, which will be large enough to accommodate whatever string you want to copy to it - 8 characters will work in the sample code you've given:
class Infix : public Stack {
string outputString;
char operatorArray[8]; // Make this member a REAL array of characters.
//..
Your variable char operatorArray[] have no memory allocated when your constructor is called. When you use strcpy, you write to a place where you don't have permissions in your memory, and therefore on other informations.
To find these kinds of mistakes, I recommend using valgrind.
char operatorArray[]; is not allowed in Standard C++.
If you didn't see an error message then I would recommend adjusting compiler settings to follow the standard form of the language, this would have saved you a lot of time.
I'm just trying to make a "Tree" where I've a ctrsis and (for now) n "Children" connected to the ctrsis by pipes; But something happen when I try to pass data through pipes from childen to parent and parent to children using stdin and stdout, specificly when I use write() cpp function.
//ctrsis.cpp
int
main(void) {
vector<WriteIn> TubesReference;
WriteIn mainTube;
TubesReference.push_back(mainTube);
const char* file = "ctrsis.cfg";
int levelOneProcesses = 0;
string line;
ifstream configFile(file);
if(configFile.is_open()){
while ( getline (configFile,line) ){
WriteIn structure = createTube(line);
TubesReference.push_back(structure);
levelOneProcesses++;
}
}else{
cout << "Unable to open file" << endl;
}
configFile.close();
if ((TubesReference[0].in = open("ctrsis.cfg", O_RDONLY)) == -1) {
std::cerr << "Error open file" << std::endl;
return 1;
}
TubesReference[0].out = TubesReference[1].pipeOut[1];
for (int i = 1; i < levelOneProcesses; ++i){
TubesReference[i].in = TubesReference[i].pipeIn[0];
if(i != TubesReference.size()-1){
TubesReference[i].out = TubesReference[i+1].pipeOut[1];
}else{
TubesReference[TubesReference.size()-1].out = 1;
}
}
pthread_t levelOneThreads[levelOneProcesses];
for(int i = 0; i < levelOneProcesses; ++i){
vector<string> vec;
istringstream iss(TubesReference[i+1].line);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(vec));
string file = "FICHEROCFG=" + vec[4];
string folder = "DIRDETRABAJO=" + vec[3];
char* formatFile = new char[file.length()+1];
memcpy(formatFile, file.c_str(), file.length()+1);
char* formatFolder= new char[folder.length()+1];
memcpy(formatFolder, folder.c_str(), folder.length()+1);
putenv(formatFile);
putenv(formatFolder);
cout << "CTRSIS: CREATE THREAD " << i << endl;
int ret = pthread_create(&levelOneThreads[i],NULL, readWriteThread, &TubesReference[i]);
if(ret != 0) {
cerr << "Error: pthread_create() failed\n" << endl;
exit(EXIT_FAILURE);
}else{
cout << "CTRSIS: JOIN THREAD " << i << endl;
pthread_join(levelOneThreads[i], NULL);
}
}
//system( "./ctreval" );
return 0;
}
void* readWriteThread(void *arg) {
sleep(3);
WriteIn *dataInOut = (struct WriteIn *) arg;
cout << "CTRSIS: METHOD" << endl;
char c;
while (read(dataInOut->in, &c, 1) > 0) {
write(dataInOut->out, &c, 1);
}
close(dataInOut->in);
close(dataInOut->out);
return NULL;
}
This is the evaluator
#include <iostream>
#include <cctype>
int
main(void) {
int c;
while ((c = std::cin.get()) != EOF) {
c = ::toupper(c);
std::cout << (char) c;
}
return 0;
}
The program writes into SQLite database, the messages are received through a wireless module. But somehow there is a memory leak every time a message is received and written to the database, after about 10 000 writes the program is using 1GB of memory.
The documentation for SQLite3 with C++ says that memory leaks are prevented with sqlite3_finalize() and sqlite3_close() which are present:
#include <iostream>
#include <string>
#include <sstream>
#include "sqlite3.h"
using namespace std;
#define DB "test.db"
sqlite3 *dbfile;
bool connectDB();
void disonnectDB();
int insOrUpdate(string s);
int select(string s);
struct messageStruct_t {
float value;
};
bool isOpenDB = false;
int main() {
int counter = 0;
while (1) {
int header = 1;
int message = rand() % 3;
if (message) {
counter ++;
switch (header) {
case 1: {
messageStruct_t recMessage;
recMessage.value = 55;
int receivedSendersID = 2;
//SQL query to get foreign key
stringstream strm_select;
strm_select << "SELECT id FROM table1 WHERE sendersID="
<< receivedSendersID;
string s_select = strm_select.str();
cout << "SQL query: " << s_select << endl;
int sendersID = select(s_select);
cout << "Sender's ID: " << sendersID << endl;
if (sendersID == 0) {
cout << "Error: Sender doesn't exist\n";
} else {
stringstream strm_insert;
strm_insert << "INSERT into table2(id,value,sender_id) values("
<< counter << ", "
<< recMessage.value << ", " << sendersID << ")";
string s_insert = strm_insert.str();
cout << "SQL query: " << s_insert << endl;
insOrUpdate(s_insert);
cout << "Recorded data: " << recMessage.value << endl;
}
}
default: {
break;
}
}
}
}
}
bool connectDB () {
if (sqlite3_open(DB, &dbfile) == SQLITE_OK) {
isOpenDB = true;
return true;
}
return false;
}
void disonnectDB () {
if ( isOpenDB == true ) {
sqlite3_close(dbfile);
}
}
int insOrUpdate(string s) {
if (!connectDB()) {
return 0;
}
char *str = &s[0];
sqlite3_stmt *statement;
int result;
const char *query = str;
if (sqlite3_prepare(dbfile, query, -1, &statement, 0) == SQLITE_OK) {
result = sqlite3_step(statement);
//the documentation says that this destroys the statement and prevents memory leaks
sqlite3_finalize(statement);
return result;
}
//and this destroys the db object and prevents memory leaks
disonnectDB();
return 0;
}
int select(string s) {
if (!connectDB()) {
return 0;
}
char *str = &s[0];
sqlite3_stmt *statement;
const char *query = str;
string returned;
if (sqlite3_prepare(dbfile, query, -1, &statement, 0) == SQLITE_OK) {
int ctotal = sqlite3_column_count(statement);
int res = 0;
while (1) {
res = sqlite3_step(statement);
if (res == SQLITE_ROW) {
for (int i = 0; i < ctotal; i++) {
string s = (char*)sqlite3_column_text(statement, i);
cout << s << " ";
returned = s;
}
cout << endl;
}
if (res == SQLITE_DONE || res == SQLITE_ERROR) {
cout << "done " << endl;
break;
}
}
} else {
cout << "Can't prepare" << endl;
return 0;
}
sqlite3_finalize(statement);
disonnectDB();
int result;
stringstream convert(returned);
if (!(convert >> result)) {
result = 0;
}
return result;
}
CREATE TABLE table1 (
id INTEGER NOT NULL,
sendersID INTEGER,
PRIMARY KEY (id)
);
CREATE TABLE table2 (
id INTEGER NOT NULL,
value FLOAT,
sender_id INTEGER,
FOREIGN KEY(sender_id) REFERENCES table1 (id)
);
INSERT INTO table1(sendersID) values(2);
In your connectDB(..) call , you don't check if the database is already open before opening it again. Your memory leak is probably from the repeated mappings of this database into your memory space.
There may be other issues with this program but the change below to connectDB(..) should help with the leak on every successful insert.
bool connectDB() {
if (false == isOpenDB && sqlite3_open(DB, &dbfile) == SQLITE_OK) {
isOpenDB = true;
}
return isOpenDB;
}
You should definitely use RAII for your connections and also for your statements. There are several places where you return early without cleaning up statements and/or closing the connection.
When I Create An Instance of the following class using Game newGame; it throws a c1001 error stating that there was a compiler error.
game.h:
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <conio.h>
#include "cls.h"
#include "explode.h"
using namespace std;
class Game
{
private:
explode EXP;
CLS cls;
string _SaveGame, _DIRECTORY;
int _GAMEDATA[500];
string _DATATITLES[500] = { "Ticks", "Dwarves", "Grain Mills", "Lumber Mills", "Mines", "Grain Workers", "Lumber Workers", "Mine Workers", "Grain Mill Experts", "Lumber Mill Experts", "Mine Experts" };
public:
void CS()
{
cls.clear();
}
void SetSaveName(string SaveName)
{
_SaveGame = SaveName;
}
void init(string directory)
{
_DIRECTORY = directory;
cout << "Init Game" << endl;
CS();
ofstream gameSave;
gameSave.open(_DIRECTORY + _SaveGame + ".save", ofstream::out | ofstream::app);
cout << "Game Saved As: " << _DIRECTORY + _SaveGame + ".save";
if (!gameSave.good())
{
// Write New Data To File
cout << "Game Saved As: " << _DIRECTORY + _SaveGame + ".save";
gameSave.flush();
gameSave << "0\n"; // TICKS
gameSave.flush();
gameSave << "7\n"; // Dwarves
gameSave.flush();
gameSave << "1\n"; // Grain Mills
gameSave.flush();
gameSave << "1\n"; // Lumber Mill
gameSave.flush();
gameSave << "1\n"; // Mine
gameSave.flush();
gameSave << "2\n"; // Grain Mill Workers
gameSave.flush();
gameSave << "2\n"; // Lumber Mill Workers
gameSave.flush();
gameSave << "3\n"; // Mine Workers
gameSave.flush();
gameSave << "1\n"; // Grain Mill Experts
gameSave.flush();
gameSave << "1\n"; // Lumber Mill Experts
gameSave.flush();
gameSave << "1\n"; // Mine Experts
gameSave.flush();
gameSave << "ENDFILE";
gameSave.flush();
}
else
{
// Read Data From File
loadGame(_SaveGame);
}
bool GameLoop = true;
while (GameLoop)
{
// Begin Game Loop Instance
printData();
string in;
bool parseDataLoop = 1;
while (parseDataLoop)
{
in = getData();
int parseDataInt = parseData(in);
if (parseDataInt == 1) {
GameLoop = 0;
saveGame();
exit(0);
}
else if (parseDataInt == 2) {
_getch();
}
else
{
parseDataLoop = 0;
}
}
saveGame();
}
}
void GameTick()
{
_GAMEDATA[0] += 1; // Number Of Game Ticks
}
void printData()
{
CS();
for (int i = 0; i < 500; i++) {
if (_GAMEDATA[i] != NULL) {
cout << _DATATITLES[i] << " : " << _GAMEDATA[i];
}
}
}
string getData()
{
string DATA;
cin >> DATA;
return DATA;
}
int parseData(string input)
{
int quit = 0;
if (input == "help")
{
// Print List Of Commands And Descriptions:
cout << "List Of All Available Commands:" << endl;
cout << "help : Shows A List Of All Available Commands" << endl;
cout << "tick : Makes Game Progress One Tick" << endl;
cout << "tick.NUM : Makes Game Progress NUM Tick(s)" << endl;
cout << "quit : Saves Game And Terminates Program" << endl;
quit = 2;
}
else if (input == "quit")
{
quit = 1;
}
else if (input == "tick")
{
// Skip One Tick
GameTick();
}
else if (find(input, '.')) {
vector<string> output;
output = EXP.explodeStuff(input, '.');
if (output[0] == "tick") {
if (isInterger(output[1]))
{
for (int i = 0; i < stoi(output[1]); i++) {
GameTick();
}
}
else
{
cout << "ERROR: tick." << output[1] << ", is not vaid please use numbers not letters." << endl;
quit = 2;
}
}
}
else
{
cout << "ERROR: Invalid Command Please type \"help\" To See A List Of Available Commands." << endl;
quit = 2;
}
return quit;
}
void loadGame(string saveGame)
{
ifstream inData;
string temp;
inData.open(_DIRECTORY + saveGame + ".cod");
if (inData.good())
{
for (int i = 0; i < 500; i++) {
getline(inData, temp);
if (temp == "ENDFILE") { break; }
if (temp != "")
{
_GAMEDATA[i] = stoi(temp);
}
}
inData.close();
}
}
void saveGame()
{
// Update Data in file
ofstream gameSave(_DIRECTORY + _SaveGame + ".save");
gameSave.clear();
for (int i = 0; i < 500; i++) {
if (_GAMEDATA[i] != NULL) {
gameSave << _GAMEDATA[i];
}
}
gameSave << "\nENDFILE";
}
bool find(string input, char find)
{
bool RETURN = 0;
for each (char CHAR in input)
{
if (CHAR == find) {
RETURN = 1;
break;
}
}
return RETURN;
}
inline bool isInterger(const std::string & s)
{
if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
char* p;
strtol(s.c_str(), &p, 10);
return (*p == 0);
}
};
main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "game.h"
#include "programSettings.h"
#include "cls.h"
#include "explode.h" // Adds explode(string input, char delimeter), and explodePrint(vector<string> input)
using namespace std;
string _DIRECTORY = (string)getenv("APPDATA") + "/cityOfDwarves/";
vector<int> _SETTINGS; // Array To Hold All Settings In The SETTINGS.cod File
int SettingsConfigured;
explode EXP;
CLS cls;
int main()
{
SetConsoleTitle("CityOfDwarves");
programSettings pSet(_DIRECTORY);
_SETTINGS = pSet.readSettings();
if (_SETTINGS.size() > 0) {
SettingsConfigured = _SETTINGS[0];
}
else
{
SettingsConfigured = 0;
}
if (!SettingsConfigured) {
pSet.setSettings();
}
cout << "Settings Configured" << endl;
cls.clear();
cout << "Please Enter a Save Name:" << endl;
string SaveName;
cin >> SaveName;
cout << "Using: " << SaveName << ", As The Current Save File." << endl;
// Begin Game Loop
Game mainGame;
mainGame.SetSaveName(SaveName);
mainGame.init(_DIRECTORY);
char i;
cin >> i;
return 0;
}
Complete Error Code:
Severity Code Description Project File Line
Error C1001 An internal error has occurred in the compiler. CityOfDwarves C:\Users\Daniel\Documents\Visual Studio 2015\Projects\CityOfDwarves\CityOfDwarves\main.cpp 1