allocating memory with functions 
Author Message
 allocating memory with functions

Expert Opinions wanted.

I wrote 2 C programs to test a hypothesis. Although the programs compile
(gcc), run and produce correct output, (proving my hypothesis wrong),
lclint produced long lists of 33 and 39 errors.

Most errors are related to functions which return pointers to memory
they allocate or which accept NULL pointer arguments and return pointers
to freshly allocated memory.

question: what (if anything) is wrong with this function?

function:

struct node *push(struct node *pTop, struct copair *pmfhcp){
   /* takes 2 pointers, 1st to top of stack,
      2nd to a coordinate pair to be stored;
      creates storage for and returns pointer
      to new node (top of stack = head of linked list) */
  struct node *pNewTop;
  if( (pNewTop = (struct node*)malloc(sizeof(struct node))) != NULL){
        pNewTop->pmfhcp = pmfhcp;
        pNewTop->next = pTop;
        return(pNewTop);
  }else{
        return(NULL);
  }    

Quote:
}

lclint output snip:

p.c: (in function push)
p.c:114,3: Implicitly temp storage pmfhcp assigned to implicitly only:
                pNewTop->pmfhcp = pmfhcp
  Temp storage (associated with a formal parameter) is transferred to a
  non-temporary reference. The storage may be released or new aliases
created.
  (-temptrans will suppress message)
p.c:115,3: Implicitly temp storage pTop assigned to implicitly only:
                pNewTop->next = pTop
p.c:118,9: Null storage returned as non-null: (NULL)
  Function returns a possibly null pointer, but is not declared using


  annotation to the return value declaration. (-nullret will suppress
message)    

Thanks for your valuable assistance,
-mike.h
--



Thu, 13 Feb 2003 03:00:00 GMT  
 allocating memory with functions
[...]

Quote:
> lclint produced long lists of 33 and 39 errors.
> Most errors are related to functions which return pointers to memory
> they allocate or which accept NULL pointer arguments and return pointers
> to freshly allocated memory.
> question: what (if anything) is wrong with this function?

Nothing in particular, except that 'lclint' is not restricting itself
to doing the work of a classic 'lint'. Actually, its imitation of
'lint' is more like a nice by-product than part of the original idea.

The errors you list are generated by code not instrumented with

the way a particular pointer is supposed to be used. The C language
alone (until the recent addition of the 'restrict' keyword in C99) had
no means to express such "usage contracts", but lclint wants them to
give it a way of checking pointer usage.

E.g., lclint will complain whenever you assign NULL to a pointer

comment, or a globally active lclint option that make that flag the
default status for any pointer. In its default state, it will also
complain if you ever have two pointer variables of the same scope
holding the same pointer, suspecting you might loose overview and
introduce dangling pointers later, when you might 'free()' one of
them, but forget the other.

The details are all in the long and rather instructive manual for
lclint.
--

Even if all the snow were burnt, ashes would remain.
--



Fri, 14 Feb 2003 03:00:00 GMT  
 allocating memory with functions

Quote:

> Expert Opinions wanted.

> I wrote 2 C programs to test a hypothesis. Although the programs compile
> (gcc), run and produce correct output, (proving my hypothesis wrong),
> lclint produced long lists of 33 and 39 errors.

> Most errors are related to functions which return pointers to memory
> they allocate or which accept NULL pointer arguments and return pointers
> to freshly allocated memory.

> question: what (if anything) is wrong with this function?

> function:

> struct node *push(struct node *pTop, struct copair *pmfhcp){
>    /* takes 2 pointers, 1st to top of stack,
>       2nd to a coordinate pair to be stored;
>       creates storage for and returns pointer
>       to new node (top of stack = head of linked list) */

Most coding conventions dictate that the function's contract be
described above the function, and that its implementation be
described within the body.  Your comment describes the contract,
so I'd put it above the function.  It's a matter of personal
taste, though.

Quote:
>   struct node *pNewTop;
>   if( (pNewTop = (struct node*)malloc(sizeof(struct node))) != NULL){

The return value from malloc doesn't need a cast.  All it can do
is hide other errors.

Quote:
>         pNewTop->pmfhcp = pmfhcp;
>         pNewTop->next = pTop;
>         return(pNewTop);

return doesn't require parantheses -- it's not a function.

- Show quoted text -

Quote:
>   }else{
>         return(NULL);
>   }
> }

> lclint output snip:

> p.c: (in function push)
> p.c:114,3: Implicitly temp storage pmfhcp assigned to implicitly only:
>                 pNewTop->pmfhcp = pmfhcp
>   Temp storage (associated with a formal parameter) is transferred to a
>   non-temporary reference. The storage may be released or new aliases
> created.
>   (-temptrans will suppress message)
> p.c:115,3: Implicitly temp storage pTop assigned to implicitly only:
>                 pNewTop->next = pTop

I don't know what lint's going on about here.  These lines are
both perfectly valid.  If you stored the address of pTop, on the
other hand, I would understand the warnings.

Quote:
> p.c:118,9: Null storage returned as non-null: (NULL)
>   Function returns a possibly null pointer, but is not declared using


>   annotation to the return value declaration. (-nullret will suppress
> message)


to tell it that you know it might return null.  This is a lint
convention, and probably isn't a bad idea.

/peter
--



Fri, 14 Feb 2003 03:00:00 GMT  
 allocating memory with functions

Quote:

> Expert Opinions wanted.
> I wrote 2 C programs to test a hypothesis. Although the programs compile
> (gcc), run and produce correct output, (proving my hypothesis wrong),
> lclint produced long lists of 33 and 39 errors.

I've yet to meet a version of lint which doesn't spit out long lists of
"errors" for code which in fact is perfectly well defined, only a bit
unusual. Of course, this is because looking at the broader scope of a
program is quite hard.

Quote:
> Most errors are related to functions which return pointers to memory
> they allocate or which accept NULL pointer arguments and return pointers
> to freshly allocated memory.
> question: what (if anything) is wrong with this function?

What's "wrong" is that it uses a coding style not known to the lclint authors.

Quote:
> struct node *push(struct node *pTop, struct copair *pmfhcp){
>    /* takes 2 pointers, 1st to top of stack,
>       2nd to a coordinate pair to be stored;
>       creates storage for and returns pointer
>       to new node (top of stack = head of linked list) */
>   struct node *pNewTop;
>   if( (pNewTop = (struct node*)malloc(sizeof(struct node))) != NULL){
>         pNewTop->pmfhcp = pmfhcp;
>         pNewTop->next = pTop;
>         return(pNewTop);
>   }else{
>         return(NULL);
>   }
> }
> lclint output snip:
> p.c: (in function push)
> p.c:114,3: Implicitly temp storage pmfhcp assigned to implicitly only:
>                 pNewTop->pmfhcp = pmfhcp

You could modify a node by passing in a pointer, that's how C does pass
by reference. Apparently lclint expects you to assign to *pmfhcp when
you pass in a pointer. This is of course not the expected behavior for
list-management functions.

Quote:
>   Temp storage (associated with a formal parameter) is transferred to a
>   non-temporary reference. The storage may be released or new aliases
> created.
>   (-temptrans will suppress message)

This is pointing to a _possible_ memory management issue. Who is managing
the memory pointed to by pmfhcp? When the list goes out of scope, should
it be deleted? If so, the caller of push will probably not free the
memory itself. But it should, if push returns NULL. OTOH, if no
responsibilities are transferred, this is a bogus warning. But you can't
determine that from this function, ergo this should be a warning.

Quote:
> p.c:115,3: Implicitly temp storage pTop assigned to implicitly only:
>                 pNewTop->next = pTop

Same issue as pmfhcp.

Quote:
> p.c:118,9: Null storage returned as non-null: (NULL)
>   Function returns a possibly null pointer, but is not declared using


>   annotation to the return value declaration. (-nullret will suppress
> message)

This looks like a particular annoying lint message, especially for people
with some C++ knowledge. I assume that a function returning a pointer can
return NULL, unless explicitly stating otherwise. lclint has another idea,
if you want to be able to return NULL you should state so, using the
provided syntax.

Still, I would code the function slightly different:

/*
 * Function:    push
 * Arguments: 2 pointers, 1st to top of stack,
 * 2nd to a coordinate pair to be stored;
 * Functionality:
 * creates storage for and returns pointer
 * to new node (top of stack = head of linked list)
 */

struct node *push(struct node *pTop, struct copair *pmfhcp)
{
        struct node *pNewTop;

        pNewTop = (struct node*)malloc(sizeof(struct node));
        if( pNewTop )
        {
                pNewTop->pmfhcp = pmfhcp;
                pNewTop->next = pTop;
        }
        return(pNewTop);

Quote:
}

This uses the fact that even if pNewTop is NULL, it can be returned. This
reduces the numbers of late returns in the function.

Michiel Salters
--



Fri, 14 Feb 2003 03:00:00 GMT  
 allocating memory with functions

Quote:

> Most errors are related to functions which return pointers to memory
> they allocate or which accept NULL pointer arguments and return pointers
> to freshly allocated memory.

> question: what (if anything) is wrong with this function?

> function:

> struct node *push(struct node *pTop, struct copair *pmfhcp){
>   struct node *pNewTop;
>   if( (pNewTop = (struct node*)malloc(sizeof(struct node))) != NULL){
> pNewTop->pmfhcp = pmfhcp;
> pNewTop->next = pTop;
> return(pNewTop);

Remember your scope rules. The pointer you create (pNewTop) is deallocated
at the return. What your pointing at is in heap space is nice and
malloc'd, but your pointer is freed and can be corrupted. Here's how.

Instead of using your pointer try to log it's location in memory, not
where it's pointing, inside the push call. After the return from push then
create a function that calls a function. This will cause stack frames to
be pushed for each func call. This may or may not corrupt your pointer,
but I think you have the gist.

Try declaring the new pointer before the push and then pass it in as a
parm and then use the return value for error checking of your malloc etc.

Another way would be when you enter push declare a temp *, that points at
pTop. Let pTop point at newly alloced memory and then you can link the new
top to the old top using the the temp*. I reversed your logic for the
malloc because I prefer well defined exit routines
So

int push(*pTop,parms)
{

  struct node *pNewTop; /* Temp pointer */

  pNewTop = pTop; /* hold my place please */

  if( (pTop = (struct node*)malloc(sizeof(struct node))) == NULL)
    return(NULL);

  return(Setup(pTop,pNewTop,parms))

Quote:
}

Good Luck!
--



Sat, 15 Feb 2003 03:00:00 GMT  
 allocating memory with functions

Quote:

>> struct node *push(struct node *pTop, struct copair *pmfhcp){
>>   struct node *pNewTop;
>>   if( (pNewTop = (struct node*)malloc(sizeof(struct node))) != NULL){
>> pNewTop->pmfhcp = pmfhcp;
>> pNewTop->next = pTop;
>> return(pNewTop);
> Remember your scope rules. The pointer you create (pNewTop) is
> deallocated at the return. What your pointing at is in heap space is
> nice and malloc'd, but your pointer is freed and can be
> corrupted. Here's how.

Maybe I'm missing something, but this criticism doesn't make any sense to
me.  Reformatting the code a little bit to use a style I prefer, this is:

struct node *
push(struct node *pTop, struct copair *pmfhcp)
{
    struct node *pNewTop;

    pNewTop = malloc(sizeof(struct node));
    if (pNewTop == NULL)
        return NULL;
    pNewTop->pmfhcp = pmfhcp;
    pNewTop->next = pTop;
    return pNewTop;

Quote:
}

That looks like perfectly valid code to me.  The pointer pNewTop is an
automatic variable, but that's fine because its value is being returned on
the stack as the return value of the function.  It's pointing to valid
space in the heap which isn't freed.

Am I missing some problem here?

Quote:
> Instead of using your pointer try to log it's location in memory, not
> where it's pointing, inside the push call. After the return from push
> then create a function that calls a function. This will cause stack
> frames to be pushed for each func call. This may or may not corrupt your
> pointer, but I think you have the gist.

This didn't make any sense to me at all.  push looks to me like a fairly
standard sort of function that allocates a struct and returns a pointer to
the newly allocated struct, passing along responsibility to the caller to
free it when it's done.  You certainly shouldn't need to play any games
with stack frames to get this to work fine.

--

--



Wed, 19 Feb 2003 00:39:57 GMT  
 allocating memory with functions

Quote:


> > Most errors are related to functions which return pointers to memory
> > they allocate or which accept NULL pointer arguments and return pointers
> > to freshly allocated memory.
> > question: what (if anything) is wrong with this function?
> > function:

> > struct node *push(struct node *pTop, struct copair *pmfhcp){
> >   struct node *pNewTop;
> >   if( (pNewTop = (struct node*)malloc(sizeof(struct node))) != NULL){
> > pNewTop->pmfhcp = pmfhcp;
> > pNewTop->next = pTop;
> > return(pNewTop);
> Remember your scope rules. The pointer you create (pNewTop) is deallocated
> at the return. What your pointing at is in heap space is nice and
> malloc'd, but your pointer is freed and can be corrupted. Here's how.
> Instead of using your pointer try to log it's location in memory, not
> where it's pointing, inside the push call. After the return from push then
> create a function that calls a function. This will cause stack frames to
> be pushed for each func call. This may or may not corrupt your pointer,
> but I think you have the gist.

Nonsense.

There is indeed a possibility that pNewTop is allocated on the stack - small,
many compilers will put it in a register - but even if that happens, no harm
is done. The value of the pointer is available as the return value of push().
If this is saved in another pointer - as the documentation should demand -
nothing is lost.

Let me give you a counter example:

int add(int a, int b) {
int sum = a + b;
return sum;

Quote:
}

int main() {
int x;
x =add(1,2)+add(3,4);
printf("%d",x);

Quote:
}

What else can be printed but 10? Still, the first call to add has a 'sum'
which most likely is overwritten by the second call. No compiler will ever
print 14.

[ Snipped some code based on this misunderstanding of return values. ]

Michiel Salters
--



Wed, 19 Feb 2003 00:40:38 GMT  
 allocating memory with functions
Hans-Bernhard Broeker
Peter Burka
Michiel Salters
robert maclemale

Thanks.  I am extremely grateful for your thoughtful responses!

good luck to all,
-mike

Quote:

>Expert Opinions wanted.

>snip

--



Wed, 19 Feb 2003 00:40:30 GMT  
 allocating memory with functions
On 28 Aug 2000 21:39:15 GMT, Hans-Bernhard Broeker

Quote:


>[...]
>> lclint produced long lists of 33 and 39 errors.

>> Most errors are related to functions which return pointers to memory
>> they allocate or which accept NULL pointer arguments and return pointers
>> to freshly allocated memory.

>> question: what (if anything) is wrong with this function?

>Nothing in particular, except that 'lclint' is not restricting itself
>to doing the work of a classic 'lint'. Actually, its imitation of
>'lint' is more like a nice by-product than part of the original idea.

>The errors you list are generated by code not instrumented with

>the way a particular pointer is supposed to be used. The C language
>alone (until the recent addition of the 'restrict' keyword in C99) had
>no means to express such "usage contracts", but lclint wants them to
>give it a way of checking pointer usage.

>E.g., lclint will complain whenever you assign NULL to a pointer

>comment, or a globally active lclint option that make that flag the
>default status for any pointer. In its default state, it will also
>complain if you ever have two pointer variables of the same scope
>holding the same pointer, suspecting you might loose overview and
>introduce dangling pointers later, when you might 'free()' one of
>them, but forget the other.

>The details are all in the long and rather instructive manual for
>lclint.

Use a compiler with better diagnostics instead of lint!
I tested a bunch of code against lint and gcc a few years ago:
gcc (-Wall) found all the real issues also found by lint,
including printf, scanf and strftime format issues, and did not
produce warnings about potential problems, requiring lint
comments or options to silence it.
So if gcc -Wall, or a similar compiler with all warnings enabled,
complains about your code, there is a real /possibility/ of a
problem that you should look at and fix.
OTOH, lint will tell you about anything that may be a problem,
and may point out cases where, for example, you are failing to
test a return code from a function, or little portability issues,
which are not of concern to a compiler.
I would use a mouthy compiler with all warnings enabled for
normal checking and keep lint for the post-debugging and unit
testing once over, in case you have missed something non-obvious.

Thanks. Take care, Brian Inglis         Calgary, Alberta, Canada
--

                                use address above to reply
--



Fri, 28 Feb 2003 22:09:50 GMT  
 allocating memory with functions


Quote:
>I tested a bunch of code against lint and gcc a few years ago:
>gcc (-Wall) found all the real issues also found by lint,
>including printf, scanf and strftime format issues, and did not
>produce warnings about potential problems, requiring lint
>comments or options to silence it.
>So if gcc -Wall, or a similar compiler with all warnings enabled,
>complains about your code, there is a real /possibility/ of a
>problem that you should look at and fix.

For best results, use "gcc -Wall -O2" or higher optimization level.
Without optimization, gcc does not compute the necessary data-flow
graph and so cannot warn you "`a' might be used uninitialized in this
function".

-andy
--



Sun, 02 Mar 2003 03:39:21 GMT  
 allocating memory with functions

Quote:

> On 28 Aug 2000 21:39:15 GMT, Hans-Bernhard Broeker


>>[...]
>>> lclint produced long lists of 33 and 39 errors.

>>Nothing in particular, except that 'lclint' is not restricting itself
>>to doing the work of a classic 'lint'. Actually, its imitation of
>>'lint' is more like a nice by-product than part of the original idea.

[...]

Quote:
> Use a compiler with better diagnostics instead of lint!

Sorry, but that's missing the point. Original 'lint' may not stand
competition against a modern compiler with warnings cranked up high
like 'gcc -Wall -W -O -ansi -pedantic' ('-Wall' alone doesn't really
cut it). But we were talking about 'lclint', here, which is a
completely different thing. It can do checks neither traditional
'lint' nor gcc ever even dreamt of.

And even 'lint' can detect some types of errors you'll have a hard
time noticing with 'gcc -Wall' alone. Like differences in function
prototypes among separately compiled which aren't properly accounted
for by #include's of correctly written headers.

Until 'gcc' learns to warn about any non-static prototype or global
variable declaration found inside the compiled main source file,
rather than in headers, it cannot replace 'lint', by a wide margin.

--

Even if all the snow were burnt, ashes would remain.
--



Sun, 02 Mar 2003 03:41:48 GMT  
 
 [ 13 post ] 

 Relevant Pages 

1. allocate memory for function

2. Allocating memory for function argument

3. allocating memory in one function and freeing it with another function

4. Allocating memory inside a function

5. allocating memory and processing thru function.

6. Do the string functions allocate memory?

7. standard variadic functions allocate memory?

8. getline function that allocates memory on-the-fly

9. allocate memory in a function

10. C functions that allocate memory

11. Freeing memory allocated inside a function

12. How to access memory allocated in function

 

 
Powered by phpBB® Forum Software