?
Solved

Pointer and Strings

Posted on 2004-11-05
3
Medium Priority
?
310 Views
Last Modified: 2008-03-10
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


0
Comment
Question by:Kgc
3 Comments
 
LVL 60

Expert Comment

by:Julian Hansen
ID: 12502795
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
 
LVL 21

Accepted Solution

by:
MogalManic earned 600 total points
ID: 12503089
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
 

Author Comment

by:Kgc
ID: 12531016
Dear julianH and MogalManic,

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

Thanks alot.

Kgc
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
Make the most of your online learning experience.
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
Progress

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question