[comp.lang.c] Turbo C help wanted

jim.nutt@p11.f15.n114.z1.fidonet.org (jim nutt) (10/07/88)

 > From: yilin@caen.engin.umich.edu (Zhao)
 > Message-ID: <3ee6a59e.14927@asterix.engin.umich.edu>
 > parts in my posting. Actually, my key problem is I couldn't use RETURN 
 > although system
 > always give me "Null pointer assignment" error the final results are not 

bingo!  there's your problem... your assigning to a null pointer, which on pc compatible hardware has effects ranging from annoying to BRS (big red switch) time.

 > affected. The program  
 > did work when running on BSD4.2 unix system (DOMAIN C COMPILER) by using 
 > either RETURN or BREAK.
 > However Turbo C (1.5) doesn't take them. I couldn't believe this!!! My 

turbo c does accept return and break... the problem is the NULL pointer assignment.

 > friend and me have spent
 > several days and still don't know what is going on. It seems to us the 
 > return address is
 > lost after building linked list, but I still don't know how to fix it 
 > yet. When I compile the
 > code in Turbo C "Test stack overflow" option is ON and no "stack 
 > overflow" error message is
 > detected at run time. I doubt Turbo C compiler has some bugs.

i doubt it does not have bugs, but that's beside the point!


(bunches of irrelevant quoted code skipped)

 > >TREEPTR create_node(info)
 > >TREENODE info
 > >   {
 > >   TREEPTR temp;
 > >
 > >   temp = (TREEPTR)calloc(1, sizeof(TREENODE));
 > >   temp->num = info.num;
 > >   temp->x = info.x;
 > >   temp->y = info.y;
 > >   temp->next = NULL;
 > >   return(temp);
 > >   }

your problem is in this function.  what memory model are you using?  if small or medium model, you've less than 64k of heap space to play with and are probably running out of memory, thus calloc() returns NULL.  medium and small models are the ones in which a NULL pointer assignment is just annoying.  large or compact model on the other hand, means that a null pointer assignment is going straight into the interrupt vector table...  and that can ruin your day!  you need to check temp for NULL after the call



oc() and abort with an error if it comes up NULL.  it means you've run out of heap space.

jim nutt
'the computer handyman'



--  
St. Joseph's Hospital/Medical Center - Usenet <=> FidoNet Gateway
Uucp: ...{gatech,ames,rutgers}!ncar!noao!asuvax!stjhmc!15.11!jim.nutt

yilin@caen.engin.umich.edu (Zhao) (10/10/88)

In article <846.234EDDA6@stjhmc.fidonet.org>, jim.nutt@p11.f15.n114.z1.fidonet.org (jim nutt) writes:
> 
> (bunches of irrelevant quoted code skipped)
> 
>  > >TREEPTR create_node(info)
>  > >TREENODE info
>  > >   {
>  > >   TREEPTR temp;
>  > >
>  > >   temp = (TREEPTR)calloc(1, sizeof(TREENODE));
>  > >   temp->num = info.num;
>  > >   temp->x = info.x;
>  > >   temp->y = info.y;
>  > >   temp->next = NULL;
>  > >   return(temp);
>  > >   }
> 
> your problem is in this function.  what memory model are you using?  if small or medium model, you've less than 64k 
> of heap space to play with and are probably running out of memory, thus calloc() returns NULL.  medium and small 
> models are the ones in with a NULL pointer assignment is just annoying. large or compact model on the other hand,
> means that a null pointer assignment is going straight into the interrupt vector table... and that can ruin your
> day! you need to check temp for NULL after the call 
>  

I may have to repost my whole funciton again to avoid confusion. Please notice some omission of first posting.  

/*================================================================*/
/*   This function allocate a memory location for a node according
  to given information, i.e., start or new.
*/

TREEPTR create_node(info)
TREENODE  info;
   {                         
   TREEPTR  temp;

          temp = (TREEPTR)calloc(1, sizeof(TREENODE));
          if (!temp)                                               <== If out of memory, should be 
              printf("calloc error: empty pointer created!\n");    <== reported here!

          temp->num = info.num;
          temp->x = info.x;
          temp->y = info.y;  
          temp->forb = info.forb;
          temp->g = info.g;
          temp->next = NULL;
          return(temp);
   }
/*================================================================*/

I did use the way you sugessted. I also tried large and huge models when small did not work.   
Unfortunately, none of them works. "Null pointer assignment" only appears when we use EXIT(0)
instead of RETURN or when Version 1.5 is used. I even tried to test RETURN after each create_node().
The fact is after the 8th node was created, returning address was lost.  

I can list all of nodes just before program termination. If there is a null pointer assigned, 
can we print out the whole linked list?
 

Yilin Zhao
yilin@caen.engin.umich.edu

ejs@orawest.ARPA (10/11/88)

In article <3ef69894.14927@asterix.engin.umich.edu> yilin@caen.engin.umich.edu (Zhao) writes:
    >	[code elided]
    >          temp = (TREEPTR)calloc(1, sizeof(TREENODE));
    >          if (!temp) /* If out of memory, should be reported here! */
    >              printf("calloc error: empty pointer created!\n");
    >          temp->num = info.num;
    >	[code elided]
    >	       return(temp);
    >	[code elided]
    >
    >... "Null pointer assignment" only appears when we use EXIT(0)
    >instead of RETURN or when Version 1.5 is used. ...
    >I can list all of nodes just before program termination.
    >If there is a null pointer assigned, 
    >can we print out the whole linked list?
    >
    >Yilin Zhao
    >yilin@caen.engin.umich.edu

Mr. Zhao:
  In your code above, when calloc returns null, and your test succeeds,
printf is called. Execution continues, however, to dereference this NULL
pointer, and you get the runtime error you describe. Your confusion over
the lack of error message may possibly be explained by the fact that on
many systems, unflushed i/o buffers are not necessarily flushed when
termination of a process results from a runtime error. You do in fact
call printf, but you don't necessarily see the message. If you call
exit, however, in some systems a cleanup routine is called to flush
buffers, etc., before exiting. This may explain why you get different
behavior when you call exit.

  In general, code like that you posted is terribly useful-- if you
detect an abnormal situation that will likely cause an abormal
termination due to a runtime error, then most likely you would want to
force a normal termination upon detection, in order to ensure correct
reportage of the detection.

  So, most of the time one doesn't see
	if (!good) printf("error");
but instead
	if (!good) {
	    printf("error");
	    exit(0);
	}
and in fact 
	    fprintf(stderr, "error");
is even better since stderr should be unbuffered.
If you are really paranoid, you may do a 
	    setbuf(stderr, (char *)0);
or equivalent call in main() before any other i/o;
this should ensure that stderr is unbuffered, and each
character written on it will appear in its destination as
soon as possible.

John Sebes
Odyssey Research Associates, West

swillden@wsccs.UUCP (Shawn Willden) (10/14/88)

In article <3ef69894.14927@asterix.engin.umich.edu>, yilin@caen.engin.umich.edu (Zhao) writes:
> 
> TREEPTR create_node(info)
> TREENODE  info;
>    {                         
>    TREEPTR  temp;
> 
>           temp = (TREEPTR)calloc(1, sizeof(TREENODE));
>           if (!temp)                                               <== If out of memory, should be 
>               printf("calloc error: empty pointer created!\n");    <== reported here!
> 
>           temp->num = info.num;
>           temp->x = info.x;
>           temp->y = info.y;  
>           temp->forb = info.forb;
>           temp->g = info.g;
>           temp->next = NULL;
>           return(temp);
>    }
> /*================================================================*/

I didn't get your original posting, so I don't know all the details, but
I use Turbo C quite exstensively (6-8 hrs./day) and I have run into a
problem similar to yours.  I don't remember how I fixed it, but I found
some ways to avoid it.

There may be a problem with your
structure passing.  Turbo C _should_ allow passing of a structure by
value because it is supposed to be ANSI C compatible, but it is more
portable and works.  I would suggest you pass info by pointer (since
your code never modifies info, that is not a problem) and use function
prototyping.  With prototyping, TC will automatically do all kinds of
great type checking and type conversions for you when you make function
calls.  In other words, use:

	TREEPTR creatnode (TREENODE *info);

and pass the address of info.

Those are just some suggestions that are probably not your problem but
make debugging easier.

If Turbo C gives you a NULL POINTER ASSIGNMENT error, that error could
have occurred at any time, not necessarily just before termination.  I
once had a program that executed fine for a good ten minutes after the
error occurred.  It gave me a null point assign error when it
terminated.  When I finally traced the bug down and found the place
where the null point assign had actually taken place, it turned out to be
in a function call from another source code file that was one of the
first to be executed!  That's probably not very encouraging.  I'm just
pointing out that your error could be somewhere else.

If you'd like to e-mail me your source code, I can probably find the bug
(I've had much experience at tracing reclusive bugs in TC) or at least
give you some ideas as to where to look.

swillden@wsccs

--------------------------------------------
I know I know something.  I'm just not sure what.
---------------------------------------------------

disclaimer:  Since I don't even see my employers more than an hour or so
a week, I can't very well be expected to have ALL their opinions changed
to mine, can I?