Okay, so I have two classes, call them A and B--in that order in the code. Class B instantiates class A as an array, and class B also has an error message char* variable, which class A must set in the event of an error. I created a third class with a pure virtual function to set the errorMessage variable in B, then made B a child of that third class. Class A creates a pointer to the third class, call it C--when B initializes the array of A objects, it loops through them and invokes a function in A to set A's pointer to C-- it passes "this" to that function, and then A sets the pointer to C to "this," and since C is B's parent, A can set C->errorMessage (I had to do all this because A and B couldn't simultaneously be aware of each other at compile time).
Anyways it works fine, however, and when I pass command line parameters to main(int,char**), it works unless I pass seven, eight, or more than twelve parameters to it... I narrowed it down (through commenting out lines) to the line of code, in A, which sets the pointer to C, to the value passed to it by B. This made no sense to me... I suspected a memory leak or something, but it seems wrong and I have no idea how to fix it... Also I don't get why specifically seven, eight, and more than twelve arguments don't work, 1-6 and 9-12 work fine.
Here is my code (stripped down)--
//class C
class errorContainer{
public:
virtual ~errorContainer(){ }
virtual void reportError(int,char*)=0;
};
//Class A
class switchObject{
void reportError(int,char*);
errorContainer* errorReference;
public:
void bindErrorContainer(errorContainer*);
};
//Class A member function definitions
void switchObject::reportError(int errorCode,char* errorMessage){
errorReference->reportError(errorCode,errorMessage);
}
void switchObject::bindErrorContainer(errorContainer* newReference){
errorReference=newReference; //commenting out this line fixes the problem
}
//Class B
class switchSystem: public errorContainer{
int errorCode;
char* errorMessage;
public:
switchSystem(int); //MUST specify number of switches in this system.
void reportError(int,char*);
int errCode();
char* errMessage();
switchObject* switchList;
};
//Class B member function definitions
switchSystem::switchSystem(int swLimit){
int i;
switchList=new (nothrow) switchObject[swLimit];
for(i=0;i<swLimit;i++){
switchList[i].bindErrorContainer(this);
}
errorCode=0;
errorMessage="No errors.";
}
void switchSystem::reportError(int reportErrorCode,char* reportErrorMessage){
int len=0,i;
errorCode=reportErrorCode;
if(errorMessage){
delete[] errorMessage;
}
while(reportErrorMessage[len]!='\0'){
len++;
}
errorMessage=new char[len];
for(i=0;i<=len;i++){
errorMessage[i]=reportErrorMessage[i];
}
}
int switchSystem::errCode(){
return errorCode;
}
char* switchSystem::errMessage(){
return errorMessage;
}
Anyone know what I've done wrong here?
It's bugging the crap out of me... I can't seem to fix it.
---EDIT---
okay, I have it set up the way I do so that I can use it like this in main()
int main(int argc,char** argv){
switchSystem sw (2)
sw.switchList[0].argumentCount=2;
sw.switchList[1].argumentCount=0;
sw.switchList[0].identifier="a";
sw.switchList[1].identifier="switch";
sw.init(argc,argv);
if(sw.errCode()>0){
cout<< "Error "<< sw.errCode()<< ": "<< sw.errMessage()<< endl;
}
}
this program is supposed to read the command line arguments and handle user defined "switches"--like how most command line programs handle switches, but instead of testing for all of them at the beginning of main I wanted to try to write a class and some functions to do it for me--create a switchSystem object with the number of switches, set their identifiers, whether or not they take arguments, and then pass the command line arguments to "init()" to sort it out. Then test like, if(sw.isSet("switch")){ ... } etc.
It seems scary that you:
Mix dynamic memory with static string constants ("No errors.") in the same pointer.
Use an explicit while-loop to compute the string's length; have you not heard of strlen()?
Use such low-level C-like string processing, for no good reason ... What's wrong with std::string?
Don't properly account for the terminating '\0' in the string, when allocating space for it and copying it. The length is also not stored, leaving the resulting char array rather difficult to interpret.
reportError() should be declared virtual in switchSystem, as it is in errorContainer.
char* should instead be std::string to avoid all of that needless work.
Is there some reason that you can't use an std::vector<switchObject> instead of new[]?
You shouldn't delete[] errorMessage when it points to a static literal string. This leads to undefined behavior. (Translation: Bad Thing(TM).)
Why are you iteratively counting and copying the contents of a char*? This is begging for trouble. You're not doing anything to protect yourself from harm.
Why must switchObject pass a string to switchSystem? Wouldn't it be better to simply return an error code or throw some class derived from std::exception? Or perhaps it should send a string to a global logging facility?
I think perhaps you should rethink your design instead of trying to fix this.
All of the above message contains really good advice, unless this is homework and you can't use STL I'd recommend that you follow them, your problems will be much less.
For example in this snippet
errorMessage=new char[len];
for(i=0;i<=len;i++){
errorMessage[i]=reportErrorMessage[i];
}
You have allocated len bytes, but you are writing to len+1 bytes, you have not allocated memory for the null terminator '\0', overwriting memory lead to nasty bugs that are difficult to trackdown.
I think the memory leak is your minor cocnern in here. You better throw this code and start over again with a new approach. This is a mess.
Related
In C++ is perfectly legitimate to do:
bool x = "hi";
Because "hi" is translated by compiler to a char array and returns a pointer to that array, which is a number and number can be implicitly converted to bool (0 is false, anything else is true).
So I have these ctor:
Exception(QString Text, bool __IsRecoverable = true);
Exception(QString Text, QString _Source, bool __IsRecoverable = true);
Sadly I figured out that calling
Exception *e = new Exception("error happened", "main.cpp #test");
It creates a new instance of "Exception" class which is created using Exception(QString Text, bool __IsRecoverable = true); constructor, which is wrong to a point.
Is there a simple way to ensure that correct function is called, other than restructuring the constructors entirely, changing position of arguments, etc?
Firstly, I'm not sure why you're dynamically allocating an exception class. I'm not sure that's ever a good idea.
You can explicitly construct a QString:
Exception e("error happened", QString("main.cpp #test"));
Or you can pass the third argument:
Exception e("error happened", "main.cpp #test", true);
Or you can add an additional constructor that takes const char* and will be preferred over the conversion to bool:
Exception(QString Text, const char* Source, bool IsRecoverable = true);
You can easily make this forward to the QString version. Also note that names beginning with an underscore and a capital letter or with two underscores are reserved.
My suggestion would be to not use default arguments. They contribute to overload resolution problems like this, and anyway it is not very readable to just see true as an argument. Whoever's reading the code then has to stop and go look up what the true means. Even if it's yourself you may forget it in a few months time when you come back to the code, especially if you do this sort of thing a lot.
For example:
struct Exception: public whatever
{
Exception(char const *text);
Exception(char const *text, char const *source);
};
struct RecoverableException: public Exception
{
RecoverableException(char const *text);
RecoverableException(char const *text, char const *source);
};
It's a little bit more typing in this source file but the payoff is that your code which actually uses the exceptions is simpler and clearer.
To implement these constructors you could have them all call a particular function in the .cpp file with relevant arguments selecting which behaviour you want.
I have a preference for using char const * rather than QString as I am paranoid about two things:
unwanted conversions
memory allocation failure
If constructing a QString throws then things go downhill fast. But you may choose to not worry about this possibility because if the system ran out of memory and your exception handling doesn't prepare for that possibility then it's going to terminate either way.
I am learning C++ and very new at using classes, and I am getting very confused in trying to use them. I am trying to convert my existing code (which used structs) so that it uses classes - so while I know what I am trying to do I don't know if I'm doing it correctly.
I was told that when using functions from the class, I first need to instantiate an object of the class. So what I have tried (a snippet) in my main function is:
int main()// line 1
{
string message_fr_client = "test"; //line2
msgInfo message_processed; //line 3
message_processed.incMsgClass(message_fr_client); //line 4
if (!message_processed.priority_check(qos_levels, message_processed)) //line 5
cout << "failure: priority level out of bounds\n"; //line 6
return 0; //line 7
}
Could you help me clarify if my following assumptions are correct? The compiler is not showing any error and so I don't know if it is error-free, or if there are ones lurking beneath.
At line 4, is the function incMsgClass being performed on the string message_fr_client and returning the resultant (and modified) message_processed?
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/*arguments*/)?
I haven't included the body of the functions because I know they work - I would just like to find out how the class functions interact. Please let me know if I can be clearer - just trying to clear up some confusion here.
Here is my class:
#ifndef clientMsgHandling_H
#define clientMsgHandling_H
#include <list>
#include <map>
#include <queue>
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
/*classifying message*/
msgInfo incMsgClass(std::string original_msg);
/*message error checks*/
bool priority_check(int syst_priority, msgInfo msg); //check that message is within qos levels
bool route_check(std::map<std::pair<int, int>, int> route_table, msgInfo msg); //check that route exists
void getPath(msgInfo msg, std::map<std::pair<int, int>, int> route_info, int max_hop);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
#endif
While it may compile (and even run), there are a few oddities with the code as shown:-
First off, class methods know which object they are operating on - so your priority_check and route_check methods probably don't need msgInfo as a parameter.,
for example, your old non-class function might be like this
bool priority_check(int p, msgInfo msg)
{
return msg.priority < p;
}
But the new one should look like this:
bool msgInfo::priority_check(int p)
{
return priority < p;
}
Also, incMsgClass is a bit odd, as it's a non-static class method that returns a msgInfo object. It's difficult to tell without understanding what it's supposed to do, but it seems possible that this function should actually be a constructor, rather than a regular method.
One other thing is that you're currently passing a msgInfo by value to those methods. So if the method needed to modify the passed msgInfo, it would not have any effect. It's generally better to pass objects by reference or const reference to other methods. So, back to the previous non-method example, it should really be this.
bool priority_check(int p, const msgInfo &msg)
...
But, as I said, you probably don't need the msgInfo parameters anyway.
At line 4, is the function incMsgClass being performed on the string message_fr_client
Yes
and returning the resultant (and modified) message_processed?
Whatever it's returning, you're ignoring the return value. It can modify the object itself, yes, because the function is not const.
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
Yes
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/arguments/)?
If a member function is intended to modify one of the class members, it's just a matter of not marking that function const
Hard to tell without implementation-details, but here we go:
I. You are passing a std::string as value (C++ is call-by-value by default), so you get a copy of the std::string in your method. If you want to work on the object you passed and manipulate it, use a reference on the object, like
msgInfo incMsgClass(std::string& original_msg); // notice the ampersand
then you can change your signature to
void incMsgClass(std::string& original_msg);
as you don't need to return the std::string you passed.
II. Yes, at least according to your signature
III. Can see a node_path only as a member.
For all your questions, see C++-FAQ.
Your basic assumptions are correct.
message_processed.incMsgClass(message_fr_client); //line 4
This line is not correct. The function you call returns msgInfo which is simply dropped. You should assign it to something. But it is not as it is usually done. You should make it a constructor of msgInfo, like
class msgInfo
{
public:
msgInfo(std::string original_msg);
...
}
Then you could call it like this
msgInfo message_processed(message_fr_client);
That line would create a msgInfo that is already properly initialized.
There is another pattern for creating class instances - static creating function. In your case you could mark incMsgClass static and then call it like
msgInfo message_processed = msgInfo.incMsgClass(message_fr_client);
I seriously doubt you need this pattern here, so I'd advise to move to constructor.
As of other functions, I see no problems there. Just note that all member functions not marked as const can modify the object they are called on. So, you don't need to pass this object explicitly. For functions a pointer to the object they are called on is available by name this. Also the functions can access all class variables as if these variables are global for normal (non-member) functions.
this is my first question after long time checking on this marvelous webpage.
Probably my question is a little silly but I want to know others opinion about this. What is better, to create several specific methods or, on the other hand, only one generic method? Here is an example...
unsigned char *Method1(CommandTypeEnum command, ParamsCommand1Struct *params)
{
if(params == NULL) return NULL;
// Construct a string (command) with those specific params (params->element1, ...)
return buffer; // buffer is a member of the class
}
unsigned char *Method2(CommandTypeEnum command, ParamsCommand2Struct *params)
{
...
}
unsigned char *Method3(CommandTypeEnum command, ParamsCommand3Struct *params)
{
...
}
unsigned char *Method4(CommandTypeEnum command, ParamsCommand4Struct *params)
{
...
}
or
unsigned char *Method(CommandTypeEnum command, void *params)
{
switch(command)
{
case CMD_1:
{
if(params == NULL) return NULL;
ParamsCommand1Struct *value = (ParamsCommand1Struct *) params;
// Construct a string (command) with those specific params (params->element1, ...)
return buffer;
}
break;
// ...
default:
break;
}
}
The main thing I do not really like of the latter option is this,
ParamsCommand1Struct *value = (ParamsCommand1Struct *) params;
because "params" could not be a pointer to "ParamsCommand1Struct" but a pointer to "ParamsCommand2Struct" or someone else.
I really appreciate your opinions!
General Answer
In Writing Solid Code, Steve Macguire's advice is to prefer distinct functions (methods) for specific situations. The reason is that you can assert conditions that are relevant to the specific case, and you can more easily debug because you have more context.
An interesting example is the standard C run-time's functions for dynamic memory allocation. Most of it is redundant, as realloc can actually do (almost) everything you need. If you have realloc, you don't need malloc or free. But when you have such a general function, used for several different types of operations, it's hard to add useful assertions and it's harder to write unit tests, and it's harder to see what's happening when debugging. Macquire takes it a step farther and suggests that, not only should realloc just do _re_allocation, but it should probably be two distinct functions: one for growing a block and one for shrinking a block.
While I generally agree with his logic, sometimes there are practical advantages to having one general purpose method (often when operations is highly data-driven). So I usually decide on a case by case basis, with a bias toward creating very specific methods rather than overly general purpose ones.
Specific Answer
In your case, I think you need to find a way to factor out the common code from the specifics. The switch is often a signal that you should be using a small class hierarchy with virtual functions.
If you like the single method approach, then it probably should be just a dispatcher to the more specific methods. In other words, each of those cases in the switch statement simply call the appropriate Method1, Method2, etc. If you want the user to see only the general purpose method, then you can make the specific implementations private methods.
Generally, it's better to offer separate functions, because they by their prototype names and arguments communicate directly and visibly to the user that which is available; this also leads to more straightforward documentation.
The one time I use a multi-purpose function is for something like a query() function, where a number of minor query functions, rather than leading to a proliferation of functions, are bundled into one, with a generic input and output void pointer.
In general, think about what you're trying to communicate to the API user by the API prototypes themselves; a clear sense of what the API can do. He doesn't need excessive minutae; he does need to know the core functions which are the entire point of having the API in the first place.
First off, you need to decide which language you are using. Tagging the question with both C and C++ here makes no sense. I am assuming C++.
If you can create a generic function then of course that is preferable (why would you prefer multiple, redundant functions?) The question is; can you? However, you seem to be unaware of templates. We need to see what you have omitted here to tell if you if templates are suitable however:
// Construct a string (command) with those specific params (params->element1, ...)
In the general case, assuming templates are appropriate, all of that turns into:
template <typename T>
unsigned char *Method(CommandTypeEnum command, T *params) {
// more here
}
On a side note, how is buffer declared? Are you returning a pointer to dynamically allocated memory? Prefer RAII type objects and avoid dynamically allocating memory like that if so.
If you are using C++ then I would avoid using void* as you don't really need to. There is nothing wrong with having multiple methods. Note that you don't actually have to rename the function in your first set of examples - you can just overload a function using different parameters so that there is a separate function signature for each type. Ultimately, this kind of question is very subjective and there are a number of ways of doing things. Looking at your functions of the first type, you would perhaps be well served by looking into the use of templated functions
You could create a struct. That's what I use to handle console commands.
typedef int (* pFunPrintf)(const char*,...);
typedef void (CommandClass::*pKeyFunc)(char *,pFunPrintf);
struct KeyCommand
{
const char * cmd;
unsigned char cmdLen;
pKeyFunc pfun;
const char * Note;
long ID;
};
#define CMD_FORMAT(a) a,(sizeof(a)-1)
static KeyCommand Commands[]=
{
{CMD_FORMAT("one"), &CommandClass::CommandOne, "String Parameter",0},
{CMD_FORMAT("two"), &CommandClass::CommandTwo, "String Parameter",1},
{CMD_FORMAT("three"), &CommandClass::CommandThree, "String Parameter",2},
{CMD_FORMAT("four"), &CommandClass::CommandFour, "String Parameter",3},
};
#define AllCommands sizeof(Commands)/sizeof(KeyCommand)
And the Parser function
void CommandClass::ParseCmd( char* Argcommand )
{
unsigned int x;
for ( x=0;x<AllCommands;x++)
{
if(!memcmp(Commands[x].cmd,Argcommand,Commands[x].cmdLen ))
{
(this->*Commands[x].pfun)(&Argcommand[Commands[x].cmdLen],&::printf);
break;
}
}
if(x==AllCommands)
{
// Unknown command
}
}
I use a thread safe printf pPrintf, so ignore it.
I don't really know what you want to do, but in C++ you probably should derive multiple classes from a Formatter Base class like this:
class Formatter
{
virtual void Format(unsigned char* buffer, Command command) const = 0;
};
class YourClass
{
public:
void Method(Command command, const Formatter& formatter)
{
formatter.Format(buffer, command);
}
private:
unsigned char* buffer_;
};
int main()
{
//
Params1Formatter formatter(/*...*/);
YourClass yourObject;
yourObject.Method(CommandA, formatter);
// ...
}
This removes the resposibility to handle all that params stuff from your class and makes it closed for changes. If there will be new commands or parameters during further development you don't have to modifiy (and eventually break) existing code but add new classes that implement the new stuff.
While not full answer this should guide you in correct direction: ONE FUNCTION ONE RESPONSIBILITY. Prefer the code where it is responsible for one thing only and does it well. The code whith huge switch statement (which is not bad by itself) where you need cast void * to some other type is a smell.
By the way I hope you do realise that according to standard you can only cast from void * to <type> * only when the original cast was exactly from <type> * to void *.
This c++ code is working fine , however memory validator says that I am using a deleted pointer in:
grf->filePath = fname; Do you have any idea why ? Thank you.
Dirloader.h
// Other code
class CDirLoader
{
public:
struct TKnownGRF
{
std::string filePath;
DWORD encodingType;
DWORD userDataLen;
char *userData;
};
// Other Code
CDirLoader();
virtual ~CDirLoader();
Dirloader.cpp
// Other code
void CDirLoader::AddGroupFile(const std::string& _fname)
{
// Other code including std::string fname = _fname;
TKnownGRF *grf = new TKnownGRF;
grf->filePath = fname;
delete grf; // Just for testing purposes
P.S.: This is only an code extract. Of course if I define a struct TKnownGRF inside .cpp and use it as an actual object, gfr.filepath = something, instead of pointer grf->filepath=something, than it is ok, but I do need to have it inside *.h in CDirLoader class, due to many other vector allocations.
Since the function returns void
void CDirLoader::AddGroupFile(const std::string& _fname)
the question is what are you going to do with grf?
Are you going to delete it? If so, then, why do a new? you can just declare a TKnownGRF variable on the stack! In that case, _fname is not contributing to the logic of this method.
I guess that the class CDirLoader has a member variable of type TKnownGRF, say grf_, and that need to be used in the AddsGroupFile() method, e.g.:
grf_.filepath = _fname;
Does this happen to be using an older version of STL, say, VC6, and running multithreaded? Older versions of STL's string class used a reference counted copy on write implementation, which didn't really work in a multithreaded environment. See this KB article on VC 6.
Or, it's also possible that you are looking at the wrong problem. If you call std::string::c_str() and cache the result at all, the cached result would probably be invalidated when you modified the original string. There are a few cases where you can get away with that, but it's very much implementation specific.
I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.