Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.sys.apple2.programmer > #1318 > unrolled thread
| Started by | AppleIIGSMarc <appleiigsmarc@gmail.com> |
|---|---|
| First post | 2014-09-26 01:57 -0700 |
| Last post | 2014-09-26 14:47 -0400 |
| Articles | 11 — 7 participants |
Back to article view | Back to comp.sys.apple2.programmer
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
| From | AppleIIGSMarc <appleiigsmarc@gmail.com> |
|---|---|
| Date | 2014-09-26 01:57 -0700 |
| Subject | memcpy 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]
| From | Charlie <charlieDOTd@verEYEzon.net> |
|---|---|
| Date | 2014-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]
| From | AppleIIGSMarc <appleiigsmarc@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Charlie <charlieDOTd@verEYEzon.net> |
|---|---|
| Date | 2014-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]
| From | Steven Hirsch <snhirsch@gmail.com> |
|---|---|
| Date | 2014-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]
| From | dempson@actrix.gen.nz (David Empson) |
|---|---|
| Date | 2014-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]
| From | "Anton Treuenfels" <teamtempest@yahoo.com> |
|---|---|
| Date | 2014-09-27 11:11 -0500 |
| Subject | Calling 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]
| From | dempson@actrix.gen.nz (David Empson) |
|---|---|
| Date | 2014-09-28 14:13 +1300 |
| Subject | Re: 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]
| From | Michael J. Mahon <mjmahon@aol.com> |
|---|---|
| Date | 2014-09-28 14:56 -0500 |
| Subject | Re: 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]
| From | "Anton Treuenfels" <teamtempest@yahoo.com> |
|---|---|
| Date | 2014-09-28 23:21 -0500 |
| Subject | Re: 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]
| From | Kelvin Sherlock <email@domain.com> |
|---|---|
| Date | 2014-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