delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2004/07/27/05:30:11

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: Paul Wilkins <disk AT paradise DOT net DOT nz>
User-Agent: Mozilla Thunderbird 0.6 (Windows/20040502)
X-Accept-Language: en
MIME-Version: 1.0
Newsgroups: comp.os.msdos.djgpp
Subject: Re: assembly code of the "strange error" - program
References: <20040727041413 DOT 21318 DOT 00000463 AT mb-m18 DOT aol DOT com>
In-Reply-To: <20040727041413.21318.00000463@mb-m18.aol.com>
Lines: 85
Message-ID: <WcpNc.640$zS6.86489@news02.tsnz.net>
Date: Tue, 27 Jul 2004 21:25:54 +1200
NNTP-Posting-Host: 218.101.50.29
X-Complaints-To: abuse AT tsnz DOT net
X-Trace: news02.tsnz.net 1090920374 218.101.50.29 (Tue, 27 Jul 2004 21:26:14 NZST)
NNTP-Posting-Date: Tue, 27 Jul 2004 21:26:14 NZST
Organization: TelstraClear
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

Sterten wrote:
> OK, here is the assembly listing (excerts) for the "strange error" program.
> I haven't yet figured out, what exactly went wrong
> and why small program changes cause to program to terminate
> without error.
> 
> 
> 
> here is, what was printed with
> gcc -c -g -Wa,-a,-ad -O2 qser3.c 
> 
> I removed some lines (...) which appeared nonimportant to me
> to reduce this posting.
> The output is rather ugly, because many instructions require more than line
> and because of the the ATT-assembly-code.
> BTW. why is it used ? Is it easier for the disassembler or for historical
> reasons or ?
> The critical section, where it crashed starts below at 
> 
>   81:qser3.c       **** m55:r--;if(R[r]!=1)goto m55;
>  542              		.loc 1 81 0
> 
> 
> apparantly R is the variable with smallest address, so what
> stands before R and why is it affected by small
> changes in the program ?


R[r] is looping with the r index being reduced by one each time, so the 
program is accessing R[3], R[2], R[1], R[0], and then on to R[-1], 
R[-2], etc..

Most people will now be feeling a sense of horror, at seeing negative 
array indexes, because arrays ARE NOT supposed to have negative indicies.

The following is a quote from a C manual that I currently have to hand.

     "One of the most coimmon and troublesome errors in C programming
      occurs when an index value goes out of range for an array - that
      is, when an index value is less than zero or greater than the size
      of the array minus one."

So when you have
   int R[99]={0};
your range is R[0], R[1], R[2], etc..., R[97], R[98]

There is no R[99] element because the line "int R[99];" says that you 
want 99 elements, so C uses for its 1st element R[0]. The second element 
is R[1], the 98th element is R[97] and the 99th element is R[98]

You are not supposed to access R[99] or higher, or R[-1] or lower.

To get back to your question, what is going wrong is that R[r] is trying 
to access negative indicies (the r value). At first C lets you do that 
even though you're not supposed to, because C give you enough rope with 
which to hang yourself.

As r gets lower and lower you are moving from memory areas that you are 
not supposed to access, to memory areas that you are not ALLOWED to 
access (the General Protection Fault), which is why the crash occurs.

Why your program sometimes crashes with one compile time option and not 
wqith other options, is because the part that is crashing is walking 
backwards through memory looking for a "1" value. Some compiled versions 
may have that somewhere in the unused parts of data block, and some may 
not have it.

My question for you is, where to from here. Are you wanting to fix this 
so that it just doesn't happen, or are you wanting to delve a lot deeper 
into assembly language.

Trivia: When defining arrays the contents are determined in different ways.

int R[99]; // won't be initialised and will have different values
int S[99]={1}; // S[0]==1, S[1] to S[98] are set to 0.
int T[99]={1,2,3}; // sets T[0]==1, T[1]==2, T[2]==3, others are 0.

Now check this out.

int U[99]; memset(U, 4, sizeof(U));

memset fills the memory locations used by U with the value 4.

-- 
Paul Wilkins

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019