I added some exception handling into some functions in my Project. Before adding the error handling the program was working normally. After adding the exceptions I now get garbage values in the constructor and mutator parameters and I'm not sure where its coming from. Some of the functions are called in no other location than the constructor, so I have no idea where they are getting the garbage data from.
I also checked for memory leaks with valgrind and some debugging with gdb, but didn't find anything. I'm at my wits end. I have attached a sample of the constructor cpp below and one of the mutators with the exception handling.
Protofield.cpp
ProtoField::ProtoField(std::string t_name, std::string t_abbreviation, FieldType t_type, Base t_base, int t_mask, std::string t_description, int t_offset, int t_length){
try{
setName(t_name);
setAbbreviation(t_abbreviation);
setType(t_type);
setBase(t_base);
setMask(t_mask);
setDescription(t_description);
setOffset(t_offset);
setLength(t_length);
m_valueString = std::map<int, std::string>();
}
catch(std::runtime_error e){
std::cerr<<"Error in ProtoField Constructor"<<std::endl;
std::cerr<<e.what()<<std::endl;
return;
}
}
/*Removed for brevity*/
void ProtoField::setMask(int t_mask){
if(mask != 0){
std::stringstream ss;
ss<<"Field " << m_abbreviation << " mask previously set: "<<m_mask;
throw std::runtime_error(ss.str());
}
else{
m_mask = t_mask;
}
return;
}
/*Removed for brevity*/
ProtoField.hpp
class ProtoField{
private:
std::string m_name;
std::string m_abbreviation;
FieldType m_type;
Base m_base;
int m_mask;
std::string m_description;
int m_offset;
int m_length;
std::map<int, std::string> m_valueString;
public:
ProtoField(
std::string t_name = "",
std::string t_abbreviation = "",
FieldType t_type = FieldType::ft_invalid,
Base t_base = Base::invalid,
int t_mask = 0,
std::string t_description = "",
int t_offset = -1,
int t_length = -1
);
std::string getName();
std::string getAbbreviation();
FieldType getType();
Base getBase();
int getMask();
std::string getDescription();
int getOffset();
int getLength();
std::map<int, std::string> getValueString();
void setName(std::string t_name);
void setAbbreviation(std::string t_abbreviation);
void setType(FieldType t_type);
void setType(std::string t_typestr);
void setBase(Base t_base);
void setBase(std::string t_basestr);
void setMask(int t_mask);
void setDescription(std::string t_description);
void setOffset(int t_offset);
void setLength(int t_length);
void addValueString(int t_key, std::string t_value);
void removeValueString(int t_key);
//other functions
std::string to_string();
};
I feel as though its also worth mentioning, only integers appear to be affected. The other values including strings and enums seem to remain consistent with their previous behaviors. So in the class shown, only the mask, offset, and length show odd behaviors.
Edit: For more detail where the constructor is called I included the two functions I know of here.
void parser::parseFields(ProtoData& t_data, ptree::ptree t_subtree){
try{
std::vector<ProtoField> fields;
for(auto val : t_subtree.get_child("")){
ProtoField field;
parseField(t_data, field, val.second);
fields.push_back(field);
}
for(auto field:fields){
t_data.addField(field);
}
}
catch(ptree::ptree_bad_path error){
std::cerr<<"Bad Path to Fields"<<std::endl;
}
catch(ptree::ptree_bad_data error){
std::cerr<<"Bad Data to fields"<<std::endl;
}
}
void parser::parseField(ProtoData& t_data, ProtoField& t_field, ptree::ptree t_subtree){
try{
t_field.setAbbreviation(t_subtree.get<std::string>("abbreviation"));
t_field.setName(t_data.getName() + "_" + t_field.getAbbreviation());
t_field.setBase(t_subtree.get<std::string>("base", "none"));
t_field.setType(t_subtree.get<std::string>("type"));
}
catch(ptree::ptree_bad_path error){
std::cerr<<"Bad Path to Field"<<std::endl;
}
catch(ptree::ptree_bad_data error){
std::cerr<<"Bad Data to field"<<std::endl;
}
}
Your constructor does not initialize m_mask. You then call setMask, which reads this yet-to-be-initialzed value (assuming that the if(mask != 0) line should be if(m_mask != 0)). This is Undefined Behavior. The value read could be anything. When it is a nonzero value, the exception will be thrown.
The solution is to either initialize m_mask before calling setMask, or assign to m_mask directly in the constructor and not call the helper function. (And since the constructor sets the mask, which can only be done once, why does that function even need to exist?)
Related
I am trying to create a function that prints whatever I feed it from the class I created. I can only get some of my class object data members to work with my print function.
I have tried using pointers and references in some source codes I found online but they didn't work. After working on this problem for about a week now I feel like I have tried everything.
void print(string* object);
enum Degree { SECURITY = 1, NETWORKING = 2, SOFTWARE = 3};
class Student {
public:
Student(string ID, string first, string last, string Email, int Age, int days1, int days2, int days3, Degree StudentDegree) {
studentID = ID;
firstName = first;
lastName = last;
email = Email;
age = Age;
daysTillComplete[0] = { days1 };
daysTillComplete[1] = { days2 };
daysTillComplete[2] = { days3 };
studentDegree = StudentDegree;
return;
}
string getID() const;
void setID(string ID);
string getFirst() const;
void setFirst(string ID);
string getLast() const;
void setLast(string ID);
string getEmail() const;
void setEmail(string ID);
int getAge() const;
void setAge( int Age);
int getdays1();
int getdays2();
int getdays3();
void setDaysTilComplete(int days, int days1, int days2);
Degree getDegree() const;
void setDegree(Degree degreeType);
private:
string studentID = "No name";
string firstName = "No name";
string lastName = "No name";
string email = "No name";
int age = 7;
int daysTillComplete[3];
Degree studentDegree = NETWORKING;
};
void print(string* object) {
cout << *object << endl;
}
string Student::getID() const {
return studentID;
}
string Student::getFirst() const {
return firstName;
}
string Student::getLast() const {
return lastName;
}
string Student::getEmail() const {
return email;
}
int Student::getAge() const {
return age;
}
int Student::getdays1() {
return daysTillComplete[0];
}
int Student::getdays2() {
return daysTillComplete[1];
}
int Student::getdays3() {
return daysTillComplete[2];
}
Degree Student::getDegree() const {
return studentDegree;
}
void Student::setID(string ID) {
studentID = ID;
}
void Student::setFirst(string first) {
firstName = first;
}
void Student::setLast(string last) {
lastName = last;
}
void Student::setEmail(string Email) {
email = Email;
}
void Student::setAge(int studentAge) {
age = studentAge;
}
void Student::setDaysTilComplete(int days1, int days2, int days3) {
daysTillComplete[0] = days1;
daysTillComplete[1] = days2;
daysTillComplete[2] = days3;
}
void Student::setDegree(Degree degreeType) {
studentDegree = degreeType;
}
int main() {
Student vallery("A1", "Vallery", "Williams", "vallery.a.williams1234#gmail.com",21,52,28,32,NETWORKING);
print(&vallery.getID());
print(&vallery.getFirst());
print(&vallery.getLast());
print(&vallery.getEmail());
//print(&vallery.getAge()); <--- will not compile if this statement is in the program
//print(&vallery.getdays1()); <--- will not compile if this statement is in the program
////print(&vallery.getdays2()); <--- will not compile if this statement is in the program
////print(&vallery.getdays3()); <--- will not compile if this statement is in the program
//print(&vallery.getDegree()); <--- will not compile if this statement is in the program
cin.get();
return 0;
}
My expected results for example print(vallery.getFirst); would be print vallery. That works, but when I do print(vallery.getAge); it should be 21 but I can't even compile it because I get the "expression must be an l-value or function designator" error. Also using int instead of string for the data type of the print function doesn't work either. I must be using something incorrectly. Can someone point me in the right direction? After a bunch of research I haven't found any solutions.
There are several things are are probably going wrong with this code.
The most obvious is that your print function expects a string*. The calls that fail are those where you try and give the function something that is not a string*. For example, getAge() returns a int, where you are taking the address of the returned int. So you are trying to call print(int*) which then is failing. To solve this you can either using templating or have overloads. Here is a recommended template function:
template <typename T>
print (const T& _object)
{
cout << _object << endl;
}
A second problem, which is what is masking this first error comes from the fact you are taking a ptr instead of a reference (or a const reference as in my template function). If you want to print something, you want it to definitely be there and not a nullptr. So use references. In saying this, I think the ones that you say will work, definitely shouldn't work (even though they are string*'s) under any sane compiler. Perhaps the current error is hiding those errors.
The error “expression must be an lvalue or a function designator” comes from the fact that you are trying to take the address of an r-value. That is a value that is temporary and/or has not been bound to a name. Your getters return a copy of the value stored in your student object and this value has no address. You are trying to get the address of an addressless value, hence the error that it must be lvalue.
To solve this: Firstly don't use pointers, use a const reference. Secondly, have your getters return a const reference for objects. For example,
const string& Student::getID() const;
If your print function takes a const reference, it is able to handle a temporary variables for the cases where you return an int or other primitive type. Since your other getters return a reference to an addressable value, the print function can also take this reference without having to needlessly copy the values.
I am writing an interface for several I/O classes.
There is a function that looks for information in different kinds of files (sometimes html, sdb, txt, ...):
bool Search(std::string file, std::string field)
However, one of these requires an additional parameter to complement the SQL query. In this case the sdb needs to specify in what table the field is located.
I am trying something like the following (it does not compile, I am aware):
class fileIO{
public:
virtual ~FileIO(){};
virtual bool Search(std::string file, std::string field,
std::string additional = 0 /* for sdb only */) = 0;
}
class readHTML : fileIO{
public:
bool Search(std::string file, std::string field); //does NOT override virtual method
Is there anything that can give me the behavior I am looking for?
Is such strategy according to C++ standards?
What else could I add to replace such enforcement on the interface?
I am sorry if the title is misleading, I am looking for an alternative with that behavior. I could not find it so far.
You don't need it, I'd say.
At the caller site, there is only two possibilities: you know your specific fileIO instance is a sdbIO or you don't. If you do, you can call an overloaded version of Search defined in sdbIO which takes this additional info. If you don't, you don't and sdbIO::Search should be defined in terms of its overloaded version.
struct fileIO
{
virtual bool Search(std::string file, std::string field) = 0;
}
struct sdbIO : fileIO
{
bool Search(std::string file, std::string field, std::string additional);
bool Search(std::string file, std::string field) override
{
Search(file, field, "");
}
};
At the caller site:
void f(fileIO& io)
{
// I know this is a sdb:
dynamic_cast<sdbIO&>(io).Search("/file", "text", "WHERE answer=42");
// I don't
io.Search("/file", "text");
}
notes: do you really need a copy of those strings?
You can hide the virtual function in the non-public interface and make the public interface (with the default argument) non-virtual.
struct Interface
{
...
// public interface calls the abstract members.
bool Search(string const&a, string const&b, string const&c = "")
{
if(c.empty() && need_third_string())
throw runtime_error("search requires an additional string argument");
return search(a,b,c);
}
protected:
virtual bool need_third_string() const = 0;
virtual bool search(string const&, string const&, string const&) const=0;
};
with obvious derivations:
struct A : Interface
{
protected:
bool need_third_string() const override
{ return false; }
bool search(string const&a, string const&b, string const&) const override
{ /* search ignoring third argument */ }
};
struct B : Interface
{
protected:
bool need_third_string() const override
{ return true; }
bool search(string const&a, string const&b, string const&c) const override
{ /* search ignoring using all 3 arguments */ }
};
I don't see any problem with above two way to handle things. Still, I have just one more.
#include<bits/stdc++.h>
#include <stdexcept>
using namespace std;
typedef struct
{
std::string arg1;
std::string arg2;
std::string arg3;
} Param;
class FileIO{
public:
virtual ~FileIO(){};
virtual void Search(Param param) = 0;
};
class ReadHTML : public FileIO{
public:
void Search(Param param)
{
if(param.arg3.length() > 0) // Some logic to handle things here.
search3(param.arg1, param.arg2, param.arg3);
else
throw std::runtime_error("Bad call with param");
}
private:
void search3(std::string arg1, std::string arg2, std::string arg3)
{
std::cout << " I am called with Html::Search3" << std::endl;
}
};
class ReadTxt : public FileIO{
public:
void Search(Param param)
{
if(param.arg1.length() && param.arg2.length()) // Some logic to handle things here.
search2(param.arg1, param.arg2);
else
throw std::runtime_error("Bad call with param");
}
private:
void search2(std::string arg1, std::string arg2)
{
std::cout << " I am called with Txt::Search2" << std::endl;
}
};
// Driver program to test above function
int main()
{
FileIO *io = new ReadHTML();
Param paramHtml = {"a", "b", "c"};
io->Search(paramHtml); // Put some try .. catch
Param paramTxt = {"a", "b"};
io = new ReadTxt(); // Put some try...catch
io->Search(paramTxt);
return 0;
}
Strange problem, already looked into with several colleagues...
Using Qt Creator and Qt 4.8.5
define an object
set a number of values with setters
request values with a getters
result: getting an int no problem, all other values give segmentation fault
but with breakpoint in debugger the values are correctly shown, so they are in the object!
same code worked before, problem "just appeared". Compiler issue?
private:
int id;
QString name;
public;
int getId() { return this->id; } // OK
void setId(int id) { this->id = id; }
QString getName() { return this->name; } // SIGSEGV
void setName(QString name) { this->name = name; }
Any ideas? Same issue known?
UPDATE
Changed code to this, based on comments, still same issue
private:
int id;
QString name;
public;
int getId() { return id; } // OK
void setId(int setTo) { id = setTo; }
QString getName() { return name; } // SIGSEGV
void setName(QString setTo) { name = setTo; }
I was facing similar issue. Although I could not find the root cause of this issue, I have another observation.
If we define the getter functions outside the class declaration using scope resolution operator the code works.
QString MyClass::GetX(void) {
return mX;
}
QString MyClass::GetY(void) {
return mY;
}
class MyClass
{
public:
MyClass(){}
/* Functions for setting mX and mY strings. */
QString GetX(void);
QString GetY(void);
isDataAvailable()
{
return mAvailable;
}
private:
bool mAvailable;
QString mX;
QString mY;
};
As I understand, in C++, if we define a function within class declaration, by default it is inline... so the issue could be something related with inlining of the functions.
thinking further about the way objects are created in memory, I thought that a QString maybe doesn't reserve fixed number of bytes, which could be the cause of this strange behavior and guess what, a dummy change solved my problem...
This feels like a really "dirty" solution, but at least I can go on with my work ;-)
But any idea's on the root cause would really be appreciated! Thanks already for all the valuable comments!!!
private:
QString name; // FIRST DEFINE QSTRING
int id; // THEN DEFINE INT
public;
int getId() { return id; } // OK
void setId(int setTo) { id = setTo; }
QString getName() { return name; } // OK
void setName(QString setTo) { name = setTo; }
I created a singleton class
class AreaDataRepository {
private:
AreaDataRepository();
AreaDataRepository(const AreaDataRepository& orig);
virtual ~AreaDataRepository();
Way onGoingWay;
public:
static AreaDataRepository& Instance()
{
static AreaDataRepository singleton;
return singleton;
}
void SetOnGoingWay(Way onGoingWay);
Way const & GetOnGoingWay() const;
};
void AreaDataRepository::SetOnGoingWay(Way onGoingWay) {
this->onGoingWay = onGoingWay;
}
Way const & AreaDataRepository::GetOnGoingWay() const {
return onGoingWay;
}
header file of Way
class Way {
private:
std::string id;
std::string name;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetName(std::string name);
std::string const & GetName() const;
void SetId(std::string id);
std::string const & GetId() const;
};
Then i'm created a Way object and set vales of id and name.
Way wayNode;
wayNode.SetId("123");
wayNode.SetName("jan")
AreaDataRepository::Instance().SetOnGoingWay(wayNode);
After assign OngoingWay accessing it from another class.
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId();
the vale is not printing.
I'm going psychic here.... and I divine that your implementation of SetId is like this:
void SetId(std::string id) { id = id; }
that does not set the member variable, that sets the parameter to itself. And since your constructor most likely set the member variable id to "" you're printing empty strings. Either change the name of the parameter (to newId for example) to avoid the conflict or change the implementation to:
void SetId(std::string id) { this->id = id; }
As proof of this claim here's the result for the first version, as you see it prints nothing. And here is the result for the second, as you can see it prints the number.
The problem boils down to this: you have function parameter names that are the same as the name of your member variables and the function parameters are shadowing/hiding the member variables.
The only place this cannot happen is in a constructor's initialization list:
class Foo {
int x;
public:
Foo(int x): x(x) {} // <-- this works
void SetX(int x) { x = x; } // <-- this won't the parameter is hiding the member variable
};
Demo for the above snippet
std::cout is buffered in most implementations, if not in all. That means, the stream will wait for you to end a line before writing out any data. So, you can easily fix this by changing your output statement to
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId() << std::endl;
I used two design pattern Composite and Visitor. I have no problem with Composite.But when he began writing derived classes for input and output got some errors, solution which I did never found. Although in reality, and if everything is InputVisitor done so remained only PrintVisitor and main().
Here is my code:
UPD: I rewrite some parts of code. Now I have no erros, but it only open terminal and nothind doing...
P.S. Maybe I did not properly implement of patterns. Someone has a better idea?
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
class BaseComponent {
public:
virtual void add(BaseComponent *)=0;
virtual void accept(class Visitor &)=0;
};
class Card :public BaseComponent {
public:
Card (string bookName, vector<string> authors, int year): _bookName(bookName), _authors(authors), _year(year) {}
string getBookName() const {
return _bookName;
}
vector<string> getAuthors() const {
return _authors;
}
int getYear() const {
return _year;
}
void setBookName(string bookName) {
_bookName = bookName;
}
void setAuthors(vector<string> authors) {
copy(authors.begin(), authors.end(), _authors.begin());
}
void setYear(int year) {
_year = year;
}
void add(BaseComponent *){}
void accept(class Visitor &);
private:
string _bookName;
vector<string> _authors;
int _year;
};
class Folder :public BaseComponent {
public:
Folder(): _folderName(""), _parentFolder("") {}
Folder(string parentFolder): _folderName(""), _parentFolder(parentFolder) {}
string getFolderName() const {
return _folderName;
}
string getParentName() const {
return _parentFolder;
}
vector<BaseComponent*> getSubFolders() const {
return _subFolders;
}
void setFolderName(string folderName) {
_folderName = folderName;
}
void setParentFolder(string parentFolder) {
_parentFolder = parentFolder;
}
void add(BaseComponent *component) {
_subFolders.push_back(component);
}
void accept(class Visitor &);
private:
string _folderName;
string _parentFolder;
vector<BaseComponent*> _subFolders;
};
class Visitor {
public:
virtual void visitCard(Card *)=0;
virtual void visitFolder(Folder *)=0;
};
void Card::accept(class Visitor &visitor) {
visitor.visitCard(this);
}
void Folder::accept(class Visitor &visitor) {
visitor.visitFolder(this);
}
class InputVisitor :public Visitor {
public:
InputVisitor(string file): _file(file){}
void setFile(string file) {
_file = file;
}
void visitCard(Card *){}
void visitFolder(Folder *folder){
ifstream input(_file);
string folderName;
getline(input, folderName);
folder->setFolderName(folderName);
string fileName;
while (!input.eof()) {
input >> fileName;
if (fileName == "----") {
break;
} else {
Folder *subFolder = new Folder(folderName);
InputVisitor *inputVisitor = new InputVisitor(fileName);
subFolder->accept(*inputVisitor);
folder->add(subFolder);
}
}
while (!input.eof()) {
string name, tempAuthor;
vector<string> authors;
int n, year;
input >> name;
input >> n;
for (int i = 0; i<n; ++i) {
input >> tempAuthor;
authors.push_back(tempAuthor);
}
input >> year;
Card *subBook = new Card(name, authors, year);
folder->add(subBook);
}
input.close();
}
private:
string _file;
};
class PrintVisitor :public Visitor {
public:
PrintVisitor(string outputFile): _outputFile(outputFile) {}
void setOutputFile(string outputFile) {
_outputFile = outputFile;
}
void visitFolder(Folder *folder) {
ofstream output(_outputFile);
output << folder->getFolderName() << endl << "\t";
vector<BaseComponent*> subFolders = folder->getSubFolders();
vector<BaseComponent*>::iterator it;
for (it=subFolders.begin(); it!=subFolders.end(); ++it) {
(*it)->accept(*this);
}
output.close();
}
void visitCard(Card *card) {
ofstream output(_outputFile);
output << "Book: " << card->getBookName() << endl
<< "Author(s): ";
vector<string> authors = card->getAuthors();
for (vector<string>::iterator it=authors.begin(); it!=authors.end(); ++it) {
output << *it << " ";
}
output << endl << "Year: " << card->getYear();
output.close();
}
private:
string _outputFile;
};
int main() {
Folder root;
root.accept(*(new InputVisitor("root.txt")));
root.accept(*(new PrintVisitor("output.txt")));
return 0;
}
In this code:
InputVisitor *input;
input->setFile("root.txt");
root->accept(input); //Here
InputVisitor is a *input. Your accept function takes a reference to a visitor. Change it to:
root->accept(*input); //Here
and all will be fine, aside from the typo I mentioned in the comment.
If you remove all the class in front of names for classes, the compiler will tell you when there is a misspelled class name. Otherwise, it will just treat it as "there'll be a class named Visirot at some point in the future, and I don't really care what's in it right now.
Here is the declaration of BaseComponent::accept:
virtual void accept(class Visirot &)=0;
Here is the call:
root->accept(input); //Here
Here is the declaration of input:
InputVisitor *input;
So, first, the declaration of BaseComponent::accept apparently has a typo; Visirot should probably be Visitor.
Second, accept takes a Visitor&, but it's being called with an InputVisitor*. InputVisitor is derived from Visitor, soInputVisitor*is convertible toVisitor*andInputVisitor&is convertible toVisitor&, but there is no conversion from a pointer-to-type into a reference-to-type. So either changeBaseComponent::accept` to take a pointer or change the call to pass a reference.
First problem.
Assuming the typo Visirot is fixed, then at line 152 you have
subFolders[i]->accept(this); //Here some probrem
which passes a pointer to T where a T is expected.
Just dereference that pointer:
subFolders[i]->accept(*this);
Second problem.
Applying the same fixes in the main program would be wrong:
int main() {
BaseComponent *root;
InputVisitor *input;
input->setFile("root.txt");
root->accept(*input); //Here
PrintVisitor *output;
output->setOutputFile("output.txt");
root->accept(output); //And here
return 0;
}
This dereferences uninitialized pointers, which yields Undefined Behavior.
Don't do that.
Rewrite it as e.g.
int main() {
Folder root;
InputVisitor input;
input.setFile("root.txt");
root.accept(input); //Here
PrintVisitor output;
output.setOutputFile("output.txt");
root.accept(output); //And here
}
(and possibly replace Folder with whatever concrete class you want there.)
Third problem.
At line 144 you're assigning to a stream:
_outputFile = ofstream(outputFile);
where _outputFile is a member of type ofstream, and outputFile is a string.
This uses a C++11 feature (rvalue assignment of streams) that g++ didn't implement as of version 4.7.1.
Presumably the idea is to close _outputFile and reopen it: just do that, and the code will be much more portable:
// Add failure checking:
_outputFile.close();
_outputFile.open( outputFile );
Also, more descriptive naming would be good…
General problem set in the given code.
Compiling the above yields a number of warnings about signed/unsigned comparisons and unused local variables. Fix all that. Build at highest practical warning level, -Wall with g++ and /W4 with Visual C++, and make it compile cleanly.
Logic errors & testing.
Even when it compiles cleanly, there can and usually will remain logic errors. To root out those, devise a set of exactly reproducible tests, complete with any necessary test data.