tags:

views:

331

answers:

5

I have a class that executes the MSNP15 protocol. The protocol requires clients to perform frequent connection/disconnection to various servers like the dispatch server, login server and the switchboard server.

I decided to store the protocol related variables ( like ticket tokens, nonce etc ) as static member variables in a utility class like below:

class MsnUtility
    {
    public:
     static void SetChallengeStringL ( const char *string );

     static const char* GetChallengeString ( );

     static void SetContactTicketL ( const char *ticket );

     static const char* GetContactTicket ( );

    private:

     MsnUtility();

 static char *iChallengeString;

     static char *iContactTicket;
    };

The static variables above are initialized to NULL at startup and then newed when the tokens become available as the protocol executes.

Since I don't have access to C++ standard library ( as I am developing on Symbian S60 platform ) I cannot use the string library. Will the allocated character pointers be freed when the program exits or is there any other mechanism by which I could ensure they are freed.

I am also open to alternative design suggestions.

A: 

I don't think u need to worry about leaks after exit. Also If you are thinking about leak during the program lifetime, Go for singleton with reference counting.

Learner
Note that *most* platforms will reclaim an application's memory, but it isn't a given. If I recall correctly, Win98 didn't. For Symbian OS, check out: http://discussion.forum.nokia.com/forum/showthread.php?t=149695
outis
Then in that case go for second solution "singleton with reference counting". :-)
Learner
Could you please explain "singleton with reference counting"? Reference count of what? Whether memory is reclaimed or not at program exit is not the issue, proper design of the MsnUtility class is.
Vijay Mathew
Singleton, are you crazy? IT will bring with it, its own share of issues. Believe me guys I have used it and it is a pia if threading is also involved. I would never suggest you to use singleton because whatever can be done with singleton can be done without it. Also, it will bring with it problems which will manifest when you expect the least. So if u go ahead with it good luck to u mate!
rocknroll
@rocknroll: 'whatever can be done with singleton can be done without it':- Every problem in CS can be solved with one more level of indirection. And you can write thread-safe singletons. Can you kindly elaborate on the exact share of issues that singleton *by design* brings with it?
Abhay
@rocknroll: I would call MsnUtility::Instance() method during single threaded startup of the application, say in one of the class's constructors. I think that would suffice to make it thread safe. What say?
ardsrk
+1  A: 

If you allocate the memory, then you are the one who must release it. Since the members are static, they do not belong to any instance of the class. So you will have to ensure that the memory is released after the last possible use of the character pointers. This is often very difficult to determine.

I think a better idea in this case would be to have a singleton-class with all the needed tokens. Make this class globally accessible, provide necessary setters\getters for token-manipulation. Then when the dtor of the singleton class is called at program exit, you can de-alllocate the memory.

Something on the following lines :-

class TokenDict  {
public:
  static TokenDict& instance() {
    static TokenDict instance;
    return instance;
  }
  // getters \ setters for tokens
  void setToken(char* tptr) {
    if(token1)
      delete[] token1;
    // allocate memory for new token here
    token1 = new char[strlen(tptr) + 1];
    // copy tptr into token1
  }
  char const* getToken() const { return token1; }
private:
   ~TokenDict()
  {
    delete[] token1;
  }
  TokenDict() : token1(0) // ctor hidden
  { }
  TokenDict(TokenDict const&); // copy ctor hidden
  TokenDict& operator=(TokenDict const&); // assign op. hidden
  char* token1;
};
Abhay
In what way is this a "dict"? I only see a wrapper for a single character array. And why is the destructor public?
Ropez
@Ropez: Hmm good catch. The dtor can be made private. Just typed right-away the other day. Abt the 'dict', well, it was just a hint to wrap the tokens either in a map-kind of interface or have them as separate tokens. If one needs search functionality, the tokens may be contained in a set<char*, CStrCmp> with CStrCmp being a custom comparator for char*.
Abhay
A: 

If you're going to use multiple instances of the class MsnUtility, please note, that as some of it's fields are static - basically all instances of it will be the same. This is called a Singleton - and is probably not what you were going for.

Maciek
Maciek: I am not going to need multiple instances of MsnUtility. Just a single instance that contains all necessary protocol variables and the associated setter/getter methods.
ardsrk
+1  A: 

Why do you need a class if all the variables are static? If you want only one instance of the class, then consider making it a singleton. Then you can use the constructor and destructor to manage memory. I re-designed the class as a singleton:

class MsnUtility
{
public:
  static MsnUtility& Instance()
  {
    return instance;
  }
public:
  void SetChallengeStringL(const char* cstring)
  {
    if (iChallengeString) delete[] iChallengeString;
    iChallengeString = new char[strlen(cstring) + 1];
    strcpy(iChallengeString, cstring);
  }
  const char* GetChallengeString() const 
  {
    return iChallengeString;
  }
  void SetContactTicketL(const char* ticket)
  {
    if (iContactTicket) delete[] iContactTicket;
    iContactTicket = new char[strlen(ticket) + 1];
    strcpy(iContactTicket, ticket);
  }
  const char* GetContactTicket() const
  {
    return iContactTicket;
  }
private:
  MsnUtility() : iChallengeString(0), iContactTicket(0) { }
  ~MsnUtility()
  {
    if (iChallengeString) delete[] iChallengeString;
    if (iContactTicket) delete[] iContactTicket;
  } 
  char* iChallengeString;
  char* iContactTicket;
  static MsnUtility instance;
};

You can use the class like this:

// test.cpp

#include <iostream> // or whatever is available on your development platform.
#include "MsnUtility.h"

MsnUtility MsnUtility::instance;

int
main()
{
  MsnUtility& u = MsnUtility::Instance();
  u.SetContactTicketL("ticket");
  u.SetChallengeStringL("ch");
  std::cout << u.GetContactTicket() << ", " << u.GetChallengeString() << '\n';
  return 0;
}
Vijay Mathew
Vijay, does instance need to be a static class variable? What are the drawbacks if I make instace a local static variable and declare it in the MsnUtility::Instance() method itself as Abhay suggests.
ardsrk
If you make instance a static variable of Instance(), other member functions will not be able to use it directly. In other words, its scope is limited to Instance(). Of course, other member functions can use "instance", but with the overhead of a function call. Making instance a static local variable is OK for your current requirement, but might become an issue if more functionality is added in the future.
Vijay Mathew
@Vijay: I disagree. Other member functions can probably use instance() without the overhead of a system call, because the compiler will inline the function. But more importantly, other member functions should use 'this' instead.
Ropez
BTW: +1 to your solution, because it's basically what I was going to suggest. However, you don't need to check the pointers before calling delete, as it's safe to call delete on a NULL pointer.
Ropez
A: 

I think you can look into Qt Tower project, it is still in early stages but it has a rich class library which includes UI as well.

bashmohandes