简体   繁体   中英

storing return value from function into pointer to char variable is rightway to do?

I have written a read function which reads values from serial port(LINUX) . It returns values as pointer to char . I am calling this function in another function and storing it again in a variable as pointer to char . I occasionally got stack over flow problem and not sure if this function is creating problem. The sample is provided below. Please give some suggestions or criticism .

    char *ReadToSerialPort( )
    {
         const int buffer_size = 1024;
         char *buffer = (char *)malloc(buffer_size);
         char *bufptr = buffer;
         size_t iIn;
         int iMax = buffer+buffer_size-bufptr;

           if ( fd < 1 )
           {
            printf( "port is not open\n" );
           // return -1;
           }
           iIn = read( fd, bufptr, iMax-1 );
           if ( iIn < 0 )
           {
             if ( errno == EAGAIN )
             {
                printf( "The errror in READ" );
                return 0; // assume that command generated no response
             }
             else
                printf( "read error %d %s\n", errno, strerror(errno) );
          }
         else
          {
           // *bufptr = '\0';
           bufptr[(int)iIn<iMax?iIn:iMax] = '\0';
           if(bufptr != buffer)
               return bufptr;
         }
        free(buffer);
       return 0;

} // end ReadAdrPort

int ParseFunction(void)
{
     // some other code
     char *sResult;

    if( ( sResult = ReadToSerialPort()) >= 0)
   {
      printf("Response is %s\n", sResult);

     // code to store char in string and put into db .
   }

}

Thanks and regards, SamPrat

You do not deallocate the buffer. You need to make free after you finished working with it.

char * getData()
{
    char *buf = (char *)malloc(255);
    // Fill buffer
    return buf;
}

void anotherFunc()
{
    char *data = getData();
    // Process data
    free(data);
}

In your case I think you should free the buffer after printf :

if( ( sResult = ReadToSerialPort()) >= 0)
{
   printf("Response is %s\n", sResult);

   // code to store char in string and put into db .

   free(sResult);
}

UPDATE Static buffer

Another option to use static buffers. It could increase performance a little bit, but getData method will be not a thread-safe.

char buff[1024];

char *getData()
{
    // Write data to buff
    return buff;
}

int main()
{
    char *data = getData();
    printf("%s", data);
}

UPDATE Some notes about your code

  1. int iMax = buffer+buffer_size-bufptr; - iMax will always be 1024;
  2. I do not see any idea of using bufptr since its value is the same as buffer and you do not change it anywhere in your function;
  3. iIn = read( fd, bufptr, buffer_size-1 );
  4. You can replace bufptr[(int)iIn<iMax?iIn:iMax] = '\\0'; with bufptr[iIn] = '\\0' ;
  5. if(bufptr != buffer) is always false and this is why your pointer is incorrect and you always return 0;
  6. Do not forget to free the buffer if errno == EAGAIN is true. Currently you just return 0 without free(buffer) .

Good luck ;)

Elalfer is partially correct. You do free() your buffer, but not in every case.

For example, when you reach if ( errno == EAGAIN ) and it evaluates to true, you return without doing free on your buffer.

The best would be to pass the buffer as a parameter and make it obvious that the user must free the buffer, outside the function. (this is what basically Elalfer sais in his edited answer).

Just realized this is a C question, I blame SO filtering for this :D sorry! Disregard the following, I'm leaving it so that comments still make sense.

The correct solution should use std::vector<char> , that way the destructor handles memory deallocation for you at the end of scope.

what is the purpose of the second pointer?

char *buffer = (char *)malloc(buffer_size);
char *bufptr = buffer;

what is the purpose of this?

int iMax = buffer+buffer_size-bufptr; // eh? 

What is the purpose of this?

bufptr[(int)iIn<iMax?iIn:iMax] = '\0'; // so you pass in 1023 (iMax - 1), it reads 1023, you've effectively corrupted the last byte.

I would start over, consider using std::vector<char> , something like:

std::vector<char> buffer(1500); // default constructs 1500 chars

int iRead = read(fd, &buffer[0], 1500);

// resize the buffer if valid
if (iRead > 0)
  buffer.resize(iRead); // this logically trims the buffer so that the iterators begin/end are correct.

return buffer;

Then in your calling function, use the vector<char> and if you need a string, construct one from this: std::string foo(vect.begin(), vect.end()); etc.

When you are setting the null terminator "bufptr[(int)iIn

bufptr[iMax]=>bufptr[1024]=>one byte beyond your allocation since arrays start at 0.

Also int this case "int iMax = buffer+buffer_size-bufptr;" can be re-written as iMax = buffer_size. It makes the code less readable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM