Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.sys.apple2.programmer > #1318 > unrolled thread

memcpy crash

Started byAppleIIGSMarc <appleiigsmarc@gmail.com>
First post2014-09-26 01:57 -0700
Last post2014-09-26 14:47 -0400
Articles 11 — 7 participants

Back to article view | Back to comp.sys.apple2.programmer


Contents

  memcpy crash AppleIIGSMarc <appleiigsmarc@gmail.com> - 2014-09-26 01:57 -0700
    Re: memcpy crash Charlie <charlieDOTd@verEYEzon.net> - 2014-09-26 11:54 -0400
      Re: memcpy crash AppleIIGSMarc <appleiigsmarc@gmail.com> - 2014-09-26 10:06 -0700
        Re: memcpy crash Charlie <charlieDOTd@verEYEzon.net> - 2014-09-26 14:17 -0400
        Re: memcpy crash Steven Hirsch <snhirsch@gmail.com> - 2014-09-26 16:31 -0400
          Re: memcpy crash dempson@actrix.gen.nz (David Empson) - 2014-09-27 13:22 +1200
            Calling conventions (was Re: memcpy crash) "Anton Treuenfels" <teamtempest@yahoo.com> - 2014-09-27 11:11 -0500
              Re: Calling conventions dempson@actrix.gen.nz (David Empson) - 2014-09-28 14:13 +1300
              Re: Calling conventions (was Re: memcpy crash) Michael J. Mahon <mjmahon@aol.com> - 2014-09-28 14:56 -0500
                Re: Calling conventions (was Re: memcpy crash) "Anton Treuenfels" <teamtempest@yahoo.com> - 2014-09-28 23:21 -0500
    Re: memcpy crash Kelvin Sherlock <email@domain.com> - 2014-09-26 14:47 -0400

#1318 — memcpy crash

FromAppleIIGSMarc <appleiigsmarc@gmail.com>
Date2014-09-26 01:57 -0700
Subjectmemcpy crash
Message-ID<63dd489a-6736-45ab-bff3-0012e4a60e41@googlegroups.com>
I've been working on a program in ORCA/C (version 2.1.0) and, for some reason, it crashes anytime I try to call memcpy.  In an effort to figure out what's going on, I wrote the simplest program I could think of to test it out...

//--------------------------------------

#include <memory.h>

int source[64];
int dest[64];

int main(void)
{
   memcpy(dest, source, 16);

   return 0;
}

//--------------------------------------

This crashes for me every time I try to run it.  The number of bytes transferred doesn't seem to matter, it crashes even if it's set to 1 byte.  Also, manually copying the data with a for loop and setting each element one-by-one works with no problems.  It's late, so I may be doing something really stupid, but I'm not seeing it.  Does anyone have any idea what the problem may be?  

Thanks!

[toc] | [next] | [standalone]


#1319

FromCharlie <charlieDOTd@verEYEzon.net>
Date2014-09-26 11:54 -0400
Message-ID<m0426r$i7m$1@dont-email.me>
In reply to#1318
On 9/26/2014 4:57 AM, AppleIIGSMarc wrote:
> I've been working on a program in ORCA/C (version 2.1.0) and, for some reason, it crashes anytime I try to call memcpy.  In an effort to figure out what's going on, I wrote the simplest program I could think of to test it out...
>
> //--------------------------------------
>
> #include<memory.h>
>
> int source[64];
> int dest[64];
>
> int main(void)
> {
>     memcpy(dest, source, 16);
>
>     return 0;
> }
>
> //--------------------------------------
>
> This crashes for me every time I try to run it.  The number of bytes transferred doesn't seem to matter, it crashes even if it's set to 1 byte.  Also, manually copying the data with a for loop and setting each element one-by-one works with no problems.  It's late, so I may be doing something really stupid, but I'm not seeing it.  Does anyone have any idea what the problem may be?
>
> Thanks!

I think you need to #include <string.h> not <memory.h>.

Charlie

[toc] | [prev] | [next] | [standalone]


#1320

FromAppleIIGSMarc <appleiigsmarc@gmail.com>
Date2014-09-26 10:06 -0700
Message-ID<df99f84a-10b2-43a8-95bc-a5c3e637e3ca@googlegroups.com>
In reply to#1319
On Friday, September 26, 2014 8:54:32 AM UTC-7, Charlie wrote:
> On 9/26/2014 4:57 AM, AppleIIGSMarc wrote:
> 
> > I've been working on a program in ORCA/C (version 2.1.0) and, for some reason, it crashes anytime I try to call memcpy.  In an effort to figure out what's going on, I wrote the simplest program I could think of to test it out...
> 
> >
> 
> > //--------------------------------------
> 
> >
> 
> > #include<memory.h>
> 
> >
> 
> > int source[64];
> 
> > int dest[64];
> 
> >
> 
> > int main(void)
> 
> > {
> 
> >     memcpy(dest, source, 16);
> 
> >
> 
> >     return 0;
> 
> > }
> 
> >
> 
> > //--------------------------------------
> 
> >
> 
> > This crashes for me every time I try to run it.  The number of bytes transferred doesn't seem to matter, it crashes even if it's set to 1 byte.  Also, manually copying the data with a for loop and setting each element one-by-one works with no problems.  It's late, so I may be doing something really stupid, but I'm not seeing it.  Does anyone have any idea what the problem may be?
> 
> >
> 
> > Thanks!
> 
> 
> 
> I think you need to #include <string.h> not <memory.h>.
> 
> 
> 
> Charlie

Thanks, that was the problem...I did say it was late, right?  :)  But I'm really surprised that the linker didn't complain about an unresolved reference.  I tried compiling the program with NO includes at the top and it still linked successfully.  Apparently the linker will find any standard C function even without the proper headers?  I tried printf, strcpy, getchar and they all link successfully (and actually work unlike memcpy).  Is this the expected behavior in Ansi C or is it just Orca?  Anyway, it's good to know so that I can avoid any future problems.

Thanks,
Marc 

[toc] | [prev] | [next] | [standalone]


#1321

FromCharlie <charlieDOTd@verEYEzon.net>
Date2014-09-26 14:17 -0400
Message-ID<m04ais$h8g$1@dont-email.me>
In reply to#1320
On 9/26/2014 1:06 PM, AppleIIGSMarc wrote:
> On Friday, September 26, 2014 8:54:32 AM UTC-7, Charlie wrote:
>> On 9/26/2014 4:57 AM, AppleIIGSMarc wrote:
>>
>>> I've been working on a program in ORCA/C (version 2.1.0) and, for some reason, it crashes anytime I try to call memcpy.  In an effort to figure out what's going on, I wrote the simplest program I could think of to test it out...
>>
>>>
>>
>>> //--------------------------------------
>>
>>>
>>
>>> #include<memory.h>
>>
>>>
>>
>>> int source[64];
>>
>>> int dest[64];
>>
>>>
>>
>>> int main(void)
>>
>>> {
>>
>>>      memcpy(dest, source, 16);
>>
>>>
>>
>>>      return 0;
>>
>>> }
>>
>>>
>>
>>> //--------------------------------------
>>
>>>
>>
>>> This crashes for me every time I try to run it.  The number of bytes transferred doesn't seem to matter, it crashes even if it's set to 1 byte.  Also, manually copying the data with a for loop and setting each element one-by-one works with no problems.  It's late, so I may be doing something really stupid, but I'm not seeing it.  Does anyone have any idea what the problem may be?
>>
>>>
>>
>>> Thanks!
>>
>>
>>
>> I think you need to #include<string.h>  not<memory.h>.
>>
>>
>>
>> Charlie
>
> Thanks, that was the problem...I did say it was late, right?  :)  But I'm really surprised that the linker didn't complain about an unresolved reference.

Yes, I think it should and it certainly shouldn't crash.

> I tried compiling the program with NO includes at the top and it still linked successfully.  Apparently the linker will find any standard C function even without the proper headers?  I tried printf, strcpy, getchar and they all link successfully (and actually work unlike memcpy).

Is this the expected behavior in Ansi C or is it just Orca?

I'm not sure if finding the "standard" libraries is expected behavior in 
ANSI C but ANSI did change some of the "standard" functions.

Charlie

[toc] | [prev] | [next] | [standalone]


#1324

FromSteven Hirsch <snhirsch@gmail.com>
Date2014-09-26 16:31 -0400
Message-ID<LK2dnaCtZ7W9ULjJnZ2dnUU7-VOdnZ2d@giganews.com>
In reply to#1320
On 09/26/2014 01:06 PM, AppleIIGSMarc wrote:
> On Friday, September 26, 2014 8:54:32 AM UTC-7, Charlie wrote:

>> I think you need to #include <string.h> not <memory.h>.

> Thanks, that was the problem...I did say it was late, right?  :)  But I'm
> really surprised that the linker didn't complain about an unresolved
> reference.  I tried compiling the program with NO includes at the top and
> it still linked successfully.  Apparently the linker will find any standard
> C function even without the proper headers?  I tried printf, strcpy,
> getchar and they all link successfully (and actually work unlike memcpy).
> Is this the expected behavior in Ansi C or is it just Orca?  Anyway, it's
> good to know so that I can avoid any future problems.

K&R C assumes that all parameters not otherwise specified are type 'int'.  The 
linker cares only about symbols, so all the JSRs and JMPs are properly 
resolved.  Problem is that the compiler, not having access to the function 
declaration, built your code such that the array addresses are coerced from 
pointers to integers before calling memcpy().  As you found out, this doesn't 
work all that well.

What's odd is that integers and pointers have the same storage size (16-bits) 
on an Apple 2.  But, since evidence indicates that the parameters are not 
being setup as they should there must be something else going on that's 
particular to ORCA's implementation.

Steve

[toc] | [prev] | [next] | [standalone]


#1325

Fromdempson@actrix.gen.nz (David Empson)
Date2014-09-27 13:22 +1200
Message-ID<1lsmvj4.16nvfausqrhonN%dempson@actrix.gen.nz>
In reply to#1324
Steven Hirsch <snhirsch@gmail.com> wrote:

> On 09/26/2014 01:06 PM, AppleIIGSMarc wrote:
> > On Friday, September 26, 2014 8:54:32 AM UTC-7, Charlie wrote:
> 
> >> I think you need to #include <string.h> not <memory.h>.
> 
> > Thanks, that was the problem...I did say it was late, right?  :)  But I'm
> > really surprised that the linker didn't complain about an unresolved
> > reference.  I tried compiling the program with NO includes at the top and
> > it still linked successfully.  Apparently the linker will find any standard
> > C function even without the proper headers?  I tried printf, strcpy,
> > getchar and they all link successfully (and actually work unlike memcpy).
> > Is this the expected behavior in Ansi C or is it just Orca?  Anyway, it's
> > good to know so that I can avoid any future problems.
> 
> K&R C assumes that all parameters not otherwise specified are type 'int'.  The
> linker cares only about symbols, so all the JSRs and JMPs are properly
> resolved.  Problem is that the compiler, not having access to the function
> declaration, built your code such that the array addresses are coerced from
> pointers to integers before calling memcpy().  As you found out, this doesn't
> work all that well.
> 
> What's odd is that integers and pointers have the same storage size (16-bits)
> on an Apple 2.

Not on the IIgs. Pointers are 32-bit (only 24 bits are significant),
integers are 16-bit.

Without a valid prototype, memcpy() is being called with garbage
destination and source pointers, and probably length, because the wrong
number of bytes of parameters were passed (the pointers would each have
been converted to 16-bit ints).

ORCA/C's calling conventions are that the called function removes the
parameters from the stack (allegedly for better performance, but it
introduced all sorts of annoyances back when I was programming on the
IIgs, and I think it was a bad design choice), therefore even if the
memcpy didn't overwrite something important, the calling function will
probably crash after the return due to the stack being corrupted.

-- 
David Empson
dempson@actrix.gen.nz

[toc] | [prev] | [next] | [standalone]


#1326 — Calling conventions (was Re: memcpy crash)

From"Anton Treuenfels" <teamtempest@yahoo.com>
Date2014-09-27 11:11 -0500
SubjectCalling conventions (was Re: memcpy crash)
Message-ID<v5qdnWOBwsRSfLvJnZ2dnUVZ_jidnZ2d@earthlink.com>
In reply to#1325
"David Empson" <dempson@actrix.gen.nz> wrote in message 
news:1lsmvj4.16nvfausqrhonN%dempson@actrix.gen.nz...

> ORCA/C's calling conventions are that the called function removes the
> parameters from the stack (allegedly for better performance, but it
> introduced all sorts of annoyances back when I was programming on the
> IIgs, and I think it was a bad design choice

Could you expand on that issue? I thought the reason so many C 
implementations always make the caller clean up is that because any function 
is potentially variadic (eg., printf()), only the caller is guaranteed to 
know how many arguments have actually been pushed on the stack.

On the other hand that leads to a lot of duplicate code in the case of 
non-variadic function calls (the great majority). Hence the option in some 
compilers for a 'Pascal' calling convention, allowing non-variadic callees 
to clean up the stack instead. Some compilers automatically generate and 
push a hidden argument related to the stack size of the visible arguments, 
which again allows the callee to clean up the stack and saves space if used 
often enough.

But however cleanup is done, it shouldn't matter to a programmer. Block 
structured languages are supposed to hide such mechanics from view. Which 
order function arguments are pushed on the stack, left-to-right or 
right-to-left, is another example of something that in general is not a 
programmer's concern.

So I'm curious how that design decision, which in theory should have no 
effect on you, caused problems.

- Anton Treuenfels 

[toc] | [prev] | [next] | [standalone]


#1327 — Re: Calling conventions

Fromdempson@actrix.gen.nz (David Empson)
Date2014-09-28 14:13 +1300
SubjectRe: Calling conventions
Message-ID<1lsooct.1brn54042jss4N%dempson@actrix.gen.nz>
In reply to#1326
Anton Treuenfels <teamtempest@yahoo.com> wrote:

> "David Empson" <dempson@actrix.gen.nz> wrote in message 
> news:1lsmvj4.16nvfausqrhonN%dempson@actrix.gen.nz...
> 
> > ORCA/C's calling conventions are that the called function removes the
> > parameters from the stack (allegedly for better performance, but it
> > introduced all sorts of annoyances back when I was programming on the
> > IIgs, and I think it was a bad design choice
> 
> Could you expand on that issue? I thought the reason so many C 
> implementations always make the caller clean up is that because any function
> is potentially variadic (eg., printf()), only the caller is guaranteed to
> know how many arguments have actually been pushed on the stack.

That's the issue. ORCA/C's requires variable argument functions to fully
parse the variable arguments. They can't be lazy and bail out in error
situations, ignoring additional parameters they haven't parsed yet.

va_end() actually pulls the variable arguments off the stack, which
results in ORCA/C being non-compliaint with ANSI C. It is supposed to be
possible to use va_start() again then parse the arguments a second time.

-- 
David Empson
dempson@actrix.gen.nz

[toc] | [prev] | [next] | [standalone]


#1328 — Re: Calling conventions (was Re: memcpy crash)

FromMichael J. Mahon <mjmahon@aol.com>
Date2014-09-28 14:56 -0500
SubjectRe: Calling conventions (was Re: memcpy crash)
Message-ID<587546606433626794.229858mjmahon-aol.com@news.giganews.com>
In reply to#1326
"Anton Treuenfels" <teamtempest@yahoo.com> wrote:
> "David Empson" <dempson@actrix.gen.nz> wrote in message
> news:1lsmvj4.16nvfausqrhonN%dempson@actrix.gen.nz...
> 
>> ORCA/C's calling conventions are that the called function removes the
>> parameters from the stack (allegedly for better performance, but it
>> introduced all sorts of annoyances back when I was programming on the
>> IIgs, and I think it was a bad design choice
> 
> Could you expand on that issue? I thought the reason so many C
> implementations always make the caller clean up is that because any
> function is potentially variadic (eg., printf()), only the caller is
> guaranteed to know how many arguments have actually been pushed on the stack.
> 
> On the other hand that leads to a lot of duplicate code in the case of
> non-variadic function calls (the great majority). Hence the option in
> some compilers for a 'Pascal' calling convention, allowing non-variadic
> callees to clean up the stack instead. Some compilers automatically
> generate and push a hidden argument related to the stack size of the
> visible arguments, which again allows the callee to clean up the stack
> and saves space if used often enough.
> 
> But however cleanup is done, it shouldn't matter to a programmer. Block
> structured languages are supposed to hide such mechanics from view. Which
> order function arguments are pushed on the stack, left-to-right or
> right-to-left, is another example of something that in general is not a
> programmer's concern.
> 
> So I'm curious how that design decision, which in theory should have no
> effect on you, caused problems.
> 
> - Anton Treuenfels

Actually--as demonstrated by the OP's bug--only the *caller* knows how many
bytes were pushed onto the stack. 

And the caller can remove them trivially by resetting the stack pointer to
its value prior to the call. 
-- 
-michael - NadaNet 3.1 and AppleCrate II: http://home.comcast.net/~mjmahon

[toc] | [prev] | [next] | [standalone]


#1329 — Re: Calling conventions (was Re: memcpy crash)

From"Anton Treuenfels" <teamtempest@yahoo.com>
Date2014-09-28 23:21 -0500
SubjectRe: Calling conventions (was Re: memcpy crash)
Message-ID<MN6dnYUjwJ3GQ7XJnZ2dnUVZ_oOdnZ2d@earthlink.com>
In reply to#1328
"Michael J. Mahon" <mjmahon@aol.com> wrote in message 
news:587546606433626794.229858mjmahon-aol.com@news.giganews.com...
> "Anton Treuenfels" <teamtempest@yahoo.com> wrote:
>>
>> Could you expand on that issue? I thought the reason so many C
>> implementations always make the caller clean up is that because any
>> function is potentially variadic (eg., printf()), only the caller is
>> guaranteed to know how many arguments have actually been pushed on the 
>> stack.
>
> Actually--as demonstrated by the OP's bug--only the *caller* knows how 
> many
> bytes were pushed onto the stack.

But it can spread that knowledge around if required by the compiler writer.

> And the caller can remove them trivially by resetting the stack pointer to
> its value prior to the call.

Mmm, by adding the static compile-time count to whatever the value of the 
stack pointer is when the call returns, yes. Otherwise I don't see how 
recursive functions would work.

Still, on a 6502 that code minimally works out to something like:

  pha
  tsx
  clc
  txa
  adc #ARGSIZ+1 ;if the accumulator is preserved as shown
  tax
  txs
  pla

...which is a nine-byte overhead on every function call. So...every 28 or so 
function calls cost one of the 256 maximum available pages of memory. 36 or 
so function calls per page used for cleanup if the A-register isn't saved.

Of course that's not the only way to implement it, just a fairly 
simple-minded one.

- Anton Treuenfels 

[toc] | [prev] | [next] | [standalone]


#1322

FromKelvin Sherlock <email@domain.com>
Date2014-09-26 14:47 -0400
Message-ID<m04cd1$u8l$1@dont-email.me>
In reply to#1318
The third parameter of memcpy (defined in <string.h>) is an unsigned 
long.  Without the prototype, orca/c assumes it's an integer and there 
will be stack corruption.  #pragma lint 1 will warn about that. (I 
suggest #pragma lint -1 to enable all warnings). #pragma debug 16 will 
also generate stack-checking code to catch that at runtime (which can 
be useful with variadic functions like printf).



On 2014-09-26 08:57:27 +0000, AppleIIGSMarc said:

> I've been working on a program in ORCA/C (version 2.1.0) and, for some 
> reason, it crashes anytime I try to call memcpy.  In an effort to 
> figure out what's going on, I wrote the simplest program I could think 
> of to test it out...
> 
> //--------------------------------------
> 
> #include <memory.h>
> 
> int source[64];
> int dest[64];
> 
> int main(void)
> {
>    memcpy(dest, source, 16);
> 
>    return 0;
> }
> 
> //--------------------------------------
> 
> This crashes for me every time I try to run it.  The number of bytes 
> transferred doesn't seem to matter, it crashes even if it's set to 1 
> byte.  Also, manually copying the data with a for loop and setting each 
> element one-by-one works with no problems.  It's late, so I may be 
> doing something really stupid, but I'm not seeing it.  Does anyone have 
> any idea what the problem may be?
> Thanks!

[toc] | [prev] | [standalone]


Back to top | Article view | comp.sys.apple2.programmer


csiph-web