Clarification related to memory mgmt of char * inside a function ...

K

Karthik D

Hello All,
Basically I would like to take suggestions from programmers
about implementation of a function which processes some error
messages.(fyi:this is not a homework problem)
Let me explain my problem in detail.I have a function
which closely emulates dlerror() function.
The function is as below:

void dlerror(void *handle, char *err, size_t len)
{
char *msg;
/*
* I am using some API(Win32)which converts the error number
* to message and stores it in 'msg'.The memory for msg is
* allocated by the API.So it needs to be freed before exiting
* this function.
*/
/*
* So I try to copy msg into err using memcpy since I need
* to have the error message in calling function
*/
if (msg != NULL)
{
memcpy(err,msg,len);
}
/* freeing the memory allocated for msg */
return;
}


The function is called as follows :

int main()
{
void *hdl;
char err[256];
/*
* ....
*/
dlerror(hdl, err, sizeof(err));
if (err != NULL)
{
printf("Error message is %s\n", err);
}
else
printf("Error message is NULL\n");
return 0;
}

Is this a correct way?If I am wrong or if there are any better/good ways
could someone kindly suggest me how can I go about.

I am finding difficulty in understanding
- the memory manangement of char pointers/double char pointers
inside a function and returning their values to another function
etc..

I have read C books.But if someone could provide some real-world
insights on this,it would be helpful for me.

Thanks & Regards,
Karthik
 
S

signuts

Hello All,
Basically I would like to take suggestions from programmers
about implementation of a function which processes some error
messages.(fyi:this is not a homework problem)
Let me explain my problem in detail.I have a function
which closely emulates dlerror() function.

I'm not quite sure I understand what you're trying to do here. Maybe we
could get more information on the arguments and what they mean for
dlerror(..). As far as error detection and error number <=> error messages
goes, I personally like checking the return values of the function and
storing the error messages in a char array.

const char *err_table[] = { "error1", "error2", "error3" };
and with the help of an enum you can make the code look nice as well.
The function is as below:

void dlerror(void *handle, char *err, size_t len)
{
char *msg;
/*
* I am using some API(Win32)which converts the error number
* to message and stores it in 'msg'.The memory for msg is
* allocated by the API.So it needs to be freed before exiting
* this function.
*/
/*
* So I try to copy msg into err using memcpy since I need
* to have the error message in calling function
*/
if (msg != NULL)
{
memcpy(err,msg,len);
/* I would use strcpy here */
}
/* freeing the memory allocated for msg */
/* i'm not sure how this is freeing the memory. */
return;
}


The function is called as follows :

int main()
{
void *hdl;
char err[256];
/*
* ....
*/
dlerror(hdl, err, sizeof(err));
if (err != NULL)
{
printf("Error message is %s\n", err);
}
else
printf("Error message is NULL\n");
return 0;
}

Is this a correct way?If I am wrong or if there are any better/good ways
could someone kindly suggest me how can I go about.

I am finding difficulty in understanding
- the memory manangement of char pointers/double char pointers
inside a function and returning their values to another function
etc..

I have read C books.But if someone could provide some real-world
insights on this,it would be helpful for me.

Thanks & Regards,
Karthik
 
D

Dan Pop

In said:
void dlerror(void *handle, char *err, size_t len)
{
char *msg;
/*
* I am using some API(Win32)which converts the error number
* to message and stores it in 'msg'.The memory for msg is
* allocated by the API.So it needs to be freed before exiting
* this function. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^
There is no such need, if the function passes the value of msg back to its
caller.
*/
/*
* So I try to copy msg into err using memcpy since I need
* to have the error message in calling function
*/
if (msg != NULL)
{
memcpy(err,msg,len);
}

This does NOT ensure that err contains a proper null-terminated string.
Use something like this instead:

*err = 0;
strncat(err, msg, len - 1);

and make sure that len has a positive value.
/* freeing the memory allocated for msg */
return;
}


The function is called as follows :

int main()
{
void *hdl;
char err[256];
/*
* ....
*/
dlerror(hdl, err, sizeof(err));
if (err != NULL)

This test is downright idiotic! err is an array and the address of its
first character is guaranteed not to be a null pointer.

If dlerror() can't figure out an error message, there are two
possibilities:

1. Put a string like "failure of unknown origin" in err.

2. Return a success/failure indication to its caller, instead of being
a void function.
{
printf("Error message is %s\n", err);
}
else
printf("Error message is NULL\n");
return 0;
}

Is this a correct way?

Yes, with the objections mentioned above.
If I am wrong or if there are any better/good ways
could someone kindly suggest me how can I go about.

Simply pass back the pointer obtained from the API to the caller and
document that it is its responsibility to free it, after using it. It's
more efficient and you don't have to bother with the size of the string
containing the message. Your sample program becomes:

char *dlerror(void *handle)
{
char *msg;
/*
* I am using some API(Win32)which converts the error number
* to message and stores it in 'msg'.The memory for msg is
* allocated by the API.
*/
return msg;
}

int main()
{
void *hdl;
char *err;
/*
* ....
*/
err = dlerror(hdl);
if (err != NULL) {
printf("Error message is %s\n", err);
/* freeing the memory allocated for msg */
}
else printf("Failure of unknown origin\n");
return 0;
}

Note that everything is simpler and there is no pointless data copying.

Dan
 
K

Karthik D

Hello Dan/Signuts,
Thanks for your answers/suggestions.Basically what I wanted to achieve
is porting of dlerror to Windows(may be offtopic to clc).Sorry for bringing
a offtopic to clc.
Below is the code which achieves that.It has been suggested in
MSDN to free the lpMsgBuf allocated by FormatMessage.That's the reason
I copy it to another string and return it as mentioned in my previous
posting.

char *dlerror(void *handle)
{
LPVOID lpMsgBuf;
DWORD lastError,fmtMsgError;
char *errmsg=NULL;
int len;

if ( handle == NULL)
{
lastError = GetLastError(); //Get the Error value
if (!FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
lastError,
/* Default language */
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL ))
{
/* Handle the error. */
fmtMsgError = GetLastError();
errmsg=malloc(256);
sprintf(errmsg, "Format Message failed with errno:%ld",
fmtMsgError);
return errmsg;
}
len = strlen(lpMsgBuf);
errmsg=malloc(len+1);
strncpy(errmsg,lpMsgBuf,len);
/* Free the buffer */
LocalFree(lpMsgBuf);
return errmsg;
}
else
return errmsg;
}

If FormatMessage() fails then I am printing a hardcoded error message.
The function dlerror is called as follows:
/*
* ..... some code ........
*/
so_error = dlerror(so_handle);
if (so_error != NULL)
{
fprintf(stdout,"%s\n", so_error);
free(so_error);
so_error = NULL;
return r_ERR;
}

The variable is so_error is declared as:
char *so_error;

Is this correct?

Thanks & Regards,
Karthik
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top