Pointer and Strings

Dear Experts,
I'm using Visual C++ 6.0 sp5.
This program read record from a database.
I wish to ask some help about the pointer and strings.

This is the problem and code:


//**********************************//
int main(){

      long testing;

      long id;
      char *name = "";
      char *desc = "";

      testing = getFirstID(&id, &name, &desc);

      cout << id << " id\n";
      cout << *name << " name\n";
      cout << *desc << " desc\n";

      testing = 0;
      return 0;

}


long getFirstID(long *ID, char **Name, char **Desc){

    char *sql = "SELECT ID, Name, Desc FROM TabCustomer ORDER BY ID";

      char lTemp[128] = "";
      openDB();
      
      try{
            if(gRecordSet->State == adStateOpen)
            gRecordSet->Close();
            
                      gRecordSet->Open(sql, vtMissing, adOpenKeyset,
                                    adLockBatchOptimistic, -1);
            *channelID = long (RsITEM(gRecordSet,"ID"));

            strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Name")));
            *channelName = lTemp;
            
            cout << lTemp << " (temp)b4 clear\n";
            cout << *Name << " getname\n";

            cout << lTemp << " (temp)after clear\n";

            strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Desc")));
            *Desc = lTemp;
            
            cout << *Desc << " getdesc\n";
      }
      catch( _com_error &e){
            _bstr_t bstrSource(e.Source());
        _bstr_t bs =  _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ")
            + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ")
            + _bstr_t(e.Description()) + _bstr_t("openDB");
       
        MessageBox(0,bs,bstrSource, MB_OK);
            return 1;
      }
//**********************************//

and this is the output i get:

WAM (temp)b4 clear
WAM getname
WAM (temp)after clear
WAM Test getdesc
1 id
S name         <----- Why this isn't WAM
m desc          <----- Why this isn't WAM Test

Thanks experts


KgcAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Julian HansenCommented:
One problem you have is this

You are copying the results of the recordset into the variable lTemp

i.e.

          strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Name")));
          *channelName = lTemp;

Then later on you overwrite lTemp with another strcpy

          strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Desc")));
          *Desc = lTemp;

Because *channelName and *Desc are pointers they are both pointing to the same memory space i.e. lTemp so that is your first problem.

The second problem is that lTemp is local and not declared static so the memory allocated to it is on the stack and therefore not available when you exit the function.

You either need to dynamically allocate a buffer for each of the variables above

i.e.
 *channelName = new char[length_of_name_field] ;
  *Desc = new char[length_of_desc_field] ;

Remember to delete the buffer when you don't need it anymore
OR

statically declare your name and desc variables in main with enough space to return the result

ie

char name[256], desc[256]



0
MogalManicCommented:
julianH is right.  When you declared:
     char *name = "";
     char *desc = "";
The C++ compiler allocated a 1 byte char array on the stack and put the first character '\0' (""=char array of '\0').  And then pointed name and desc to that memory.  

The line:
 char lTemp[128] = "";
allocated a 128 character array on the stack and initiazed the 0th item as '\0'.

These lines:
          strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Name")));
          *channelName = lTemp;
copy the value from RsITEM to lTemp and then point channelName to lTemp.  NOTE:no new memory was allocated

If you do what julianH suggests, you are delegating the memory allocation to the parent function and ASSUMING the parent function has allocated enough memory to store the string.  This is fine as long as you document the MINIMUM size of "name" and "desc".  If "desc" turns out to be a memo of 270 characters then the 'desc' variable will overflow and crash your program.

I would suggest you use the power of C++ Objects to manage the strings.  Either use the native VC object library (I belive the class is called CString or CStr) or use STL (Standard Template Library).  The advantage to STL is that is a library that Microsoft did not invent.  It is implemented in many C++ compilers for many environments.  Using STL you code would be something like this (not exact because I have not programmed in C++ in many years):

//**********************************//
int main(){

     long testing;

     long id;
     String name = new String("");
     String desc = new String("");

     testing = getFirstID(&id, &name, &desc);

     cout << id << " id\n";
     cout << *name << " name\n";
     cout << *desc << " desc\n";

     testing = 0;
     //Make sure you delete after you are finished
     delete name;
     delete desc;
     return 0;

}


long getFirstID(long *ID, String &Name, String &Desc){

    char *sql = "SELECT ID, Name, Desc FROM TabCustomer ORDER BY ID";

     char lTemp[128] = "";
     openDB();
     
     try{
          if(gRecordSet->State == adStateOpen)
          gRecordSet->Close();
         
                     gRecordSet->Open(sql, vtMissing, adOpenKeyset,
                              adLockBatchOptimistic, -1);
          *channelID = long (RsITEM(gRecordSet,"ID"));

          strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Name")));
          Name = lTemp; //The C++ String object has overloaded the = operator and allocated enough space to store the string
         
          cout << lTemp << " (temp)b4 clear\n";
          cout << Name << " getname\n";

          cout << lTemp << " (temp)after clear\n";

          strcpy(lTemp, _bstr_t(RsITEM(gRecordSet,"Desc")));
          Desc = lTemp;   //The C++ String object has overloaded the = operator and allocated enough space to store the string
         
          cout << Desc << " getdesc\n";
     }
     catch( _com_error &e){
          _bstr_t bstrSource(e.Source());
        _bstr_t bs =  _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ")
            + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ")
            + _bstr_t(e.Description()) + _bstr_t("openDB");
       
        MessageBox(0,bs,bstrSource, MB_OK);
          return 1;
     }
//**********************************//

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
KgcAuthor Commented:
Dear julianH and MogalManic,

Thanks for your advise.
I change the char * to std::string.

Thanks alot.

Kgc
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.