malloc->free->damage: after normal block

A

Anuradha

Below is the code which was written VC++ 6.0 under windows environment.

Executing the same throws:
------------------
Debug Error!
Program: ccheck.exe
DAMAGE: after normal block (#41) at 0x00300160

(Press Retry to debug the application)
------------------


While the free () statement is commented the program does not report the error.

Please do let me know your views ...

Thanks in advance.

# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>

# define _DEBUG_ 1

void SetProgramName (char *);
char * GetProgramName ();
void PrintUsage ();
void PrintErrMsg (size_t);
void ClearMemory ();

char *ProgramName = NULL;

extern errno;

int
main (int argc, char *argv[])
{
SetProgramName (argv[0]);

if (argc < 2)
{
PrintUsage ();
ClearMemory ();
}

return (EXIT_SUCCESS);
}

void
SetProgramName (char *PrgName)
{

ProgramName = (char *) malloc (strlen (PrgName));

if (ProgramName == NULL)
{
PrintErrMsg (errno);
}
else
{
(void) strcpy (ProgramName, PrgName);

#if defined (_DEBUG_)
(void) fprintf (stderr, "\n Debug: ProgramName %s \n", ProgramName);
#endif

}
}

char *
GetProgramName ()
{
return (ProgramName == NULL ? NULL : ProgramName);
}

void
ClearMemory ()
{
if (strlen (ProgramName) > 0)
{
free (ProgramName);
#if 0
ProgramName = NULL;
#endif
PrintErrMsg (errno);
}
}


void
PrintErrMsg (size_t ErrNumber)
{
(void) fprintf ( stderr, \
"\n Err Number [%ld] \n Err Msg [%s] \n", \
ErrNumber, strerror (ErrNumber)
);
}

void
PrintUsage ()
{
(void) fprintf (stderr, "\n %s <> <>", GetProgramName());
}
 
B

boa

Anuradha said:
Below is the code which was written VC++ 6.0 under windows environment.

Executing the same throws:
------------------
Debug Error!
Program: ccheck.exe
DAMAGE: after normal block (#41) at 0x00300160

(Press Retry to debug the application)
------------------


While the free () statement is commented the program does not report the error.

Please do let me know your views ... [snip]

void
SetProgramName (char *PrgName)
{

ProgramName = (char *) malloc (strlen (PrgName));
ProgramName = malloc(strlen(PrgName) + 1);


boa

[snip]
 
G

Gordon Burditt

ProgramName = (char *) malloc (strlen (PrgName));

You are not allocating enough memory here.
if (ProgramName == NULL)
{
PrintErrMsg (errno);
}
else
{
(void) strcpy (ProgramName, PrgName);

And here you run over memory beyond what you allocated.

Gordon L. Burditt
 
C

Christian Kandeler

Anuradha said:
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>

# define _DEBUG_ 1

void SetProgramName (char *);
char * GetProgramName ();
void PrintUsage ();

Better:
char * GetProgramName (void);
void PrintUsage (void);
void PrintErrMsg (size_t);
void ClearMemory ();

Same here.
char *ProgramName = NULL;

extern errno;

It would be a good idea to tell your program about the type of errno.
int
main (int argc, char *argv[])
{
SetProgramName (argv[0]);

if (argc < 2)
{
PrintUsage ();
ClearMemory ();
}

return (EXIT_SUCCESS);
}

void
SetProgramName (char *PrgName)
{

ProgramName = (char *) malloc (strlen (PrgName));

You need
ProgramName = malloc (strlen (PrgName) + 1);
because the '\0' character is not counted by strlen().
if (ProgramName == NULL)
{
PrintErrMsg (errno);

This is kind of silly, since errno is a global variable anyway.
}
else
{
(void) strcpy (ProgramName, PrgName);

#if defined (_DEBUG_)
(void) fprintf (stderr, "\n Debug: ProgramName %s \n", ProgramName);
#endif

}
}

char *
GetProgramName ()
{
return (ProgramName == NULL ? NULL : ProgramName);

This is equivalent to
return ProgramName;
}

void
ClearMemory ()
{
if (strlen (ProgramName) > 0)

This is not the way to test whether the string allocation was successful.
You want
if (ProgramName != NULL)
{
free (ProgramName);
#if 0
ProgramName = NULL;
#endif
PrintErrMsg (errno);
}
}

By the way: You don't need to copy argv[0] at all, since it exists until the
end of the program.


Christian
 
F

Flash Gordon

It would be a good idea to tell your program about the type of errno.

No it isn't, it's better to delete the "extern errno;" entirely. errno
is declared appropriately by errno.h

This is kind of silly, since errno is a global variable anyway.

It is silly.

However, errno might not be a global variable, it could be a macro that
expands to a modifiable lvalue :)
 
G

Gordon Burditt

This is kind of silly, since errno is a global variable anyway.

No, it's *NOT* silly. It's perfectly possible and reasonable to
pass something else (for example, a saved version of errno from
before you tried opening the log file to put the error message in).
Being forced to save and restore errno is a pain, and so many things
MIGHT mess it up (such as opening log files, and even printf()),
it's often necessary. With a function taking an argument, you're
still sometimes stuck with saving errno, but usually not with
restoring it.

It's not that unusual to have a function return an error code or 0
to indicate success. I see that a lot inside kernels. There, you
want to deal with what the kernel returned, not errno.

Why does strerror() take an argument rather than use errno? Same
issue.

Gordon L. Burditt
 
T

Thomas Rogg

Anuradha said:
return (ProgramName == NULL ? NULL : ProgramName);
return ProgramName;

Not an error, though... See the other replys for that.

-- Thomas
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top