Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #10758 > unrolled thread
| Started by | Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> |
|---|---|
| First post | 2011-09-23 15:46 +0200 |
| Last post | 2011-09-29 21:57 +0000 |
| Articles | 8 — 6 participants |
Back to article view | Back to comp.lang.c
Inconsistent results between char/short/int Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> - 2011-09-23 15:46 +0200
Re: Inconsistent results between char/short/int Noob <root@127.0.0.1> - 2011-09-23 16:44 +0200
Re: Inconsistent results between char/short/int Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-23 17:16 +0100
Re: Inconsistent results between char/short/int Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> - 2011-09-29 14:53 +0200
Re: Inconsistent results between char/short/int Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-09-23 20:21 -0400
Re: Inconsistent results between char/short/int Nobody <nobody@nowhere.com> - 2011-09-24 18:26 +0100
Re: Inconsistent results between char/short/int Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> - 2011-09-29 14:50 +0200
Re: Inconsistent results between char/short/int Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-09-29 21:57 +0000
| From | Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> |
|---|---|
| Date | 2011-09-23 15:46 +0200 |
| Subject | Inconsistent results between char/short/int |
| Message-ID | <j5i2ki$72q$1@ccpntc8.in2p3.fr> |
Hello all,
I know it's frowned upon to post system-specific code here, but I'd like to
know if the error is in my C code (wrong pointer manipulation), in my
handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC
processor).
Basically I get different results when trying to read the memory as a single
byte, as a short or as an int (the only one that returns correct results).
Code is below.
Basically only the first 2 are correct:
# ./Peek -w 0x81600000 0x10
81600000~48006000: 00000000 00000000 00000000 00000000 ................
81600010~48006010: 00000000 00000000 00000000 80000000 ................
81600020~48006020: 000000d0 00000000 00000021 00000000 ................
81600030~48006030: 00000000 00000000 00000000 00000000 ................
# ./Peek -w 0x81600010 0xC
81600010~48006010: 00000000 00000000 00000000 80000000 ................
81600020~48006020: 000000d0 00000000 00000021 00000000 ................
81600030~48006030: 00000000 00000000 00000000 00000000 ................
# ./Peek -w 0x81600001 0x10
81600001~48006001: 00000000 00000000 00000000 00000000 ................
81600011~48006011: 00000000 00000000 00000000 00000000 ................
81600021~48006021: 00000000 00000000 00000000 00000000 ................
81600031~48006031: 00000000 00000000 00000000 00000000 ................
# ./Peek -s 0x81600000 0x20
81600000~48006000: 0000 0000 0000 0000 0000 0000 0000 0000
................
81600010~48006010: 0000 0000 0000 0000 0000 0000 0000 0000
................
81600020~48006020: 0000 0000 0000 0000 0000 0000 0000 0000
................
81600030~48006030: 0000 0000 0000 0000 0000 0000 0000 0000
................
# ./Peek -b 0x81600000 0x40
81600000~48006000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
81600010~48006010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
81600020~48006020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
81600030~48006030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
// Note: this is strictly 32-bit code with 32-bit pointers
// Note 2: only root can use this program
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iso646.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/types.h>
static char Str[]="%s [-b|s|w] address [nb]\n"
"Physical memory dump (using /dev/mem and mmap)\n"
"-b: byte dump (default)\n"
"-s: short dump\n"
"-w: word dump\n"
"nb: number of values to dump (default 1 which prints 16
bytes, 8 short or 4 words, must be less than 4kb)\n"
"Notes: You can use 0x notation for address and nb. Only root
can access /dev/mem.\n";
#define Usage { fprintf(stderr, Str, argv[0]); return 1; }
// Display printable chars as themselves, or replaces non-printable by '.'
#define F(ch, offset) ( isprint(*((unsigned char*)(ch)+(offset))) ?
*((unsigned char*)(ch)+(offset)) : '.' )
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
int main (int argc, char *argv[]) {
int Bits=8; // 8, 16 or 32
unsigned int Address=0;
unsigned int Nb=1, NbBytes;
int i, Done=0;
unsigned int Phy;
int memfd=0, Ret=0;
void *mapped_base=NULL, *Virt=NULL;
if (sizeof(void*)!=sizeof(int)) {
fprintf(stderr, "This can run only on 32-bit
systems with 32-bit pointers\n"); return 1; }
if (argc<2 or argc>4) Usage;
for (i=1; i<argc; i++) {
if (strcmp(argv[i], "-b")==0) Bits=8;
else if (strcmp(argv[i], "-s")==0) Bits=16;
else if (strcmp(argv[i], "-w")==0) Bits=32;
else if (argv[i][0]!='-') {
if (Done) {
if (argv[i][0]=='0' and
argv[i][1]=='x') Nb=strtoul(argv[i]+2, NULL, 16);
else Nb=atoi(argv[i]);
}
else {
if (argv[i][0]=='0' and
argv[i][1]=='x') Address=strtoul(argv[i]+2, NULL, 16);
else
Address=atoi(argv[i]);
Done=1;
}
}
}
NbBytes=Bits/8*Nb;
memfd = open("/dev/mem", O_RDONLY);
if (memfd < 0) { fprintf(stderr, "Can't open /dev/mem: %s\n",
strerror(errno)); return errno; }
mapped_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, memfd,
Address & ~MAP_MASK);
if (mapped_base == (void *) -1) { fprintf(stderr, "Can't map
the memory to user space: %s\n", strerror(errno)); close(memfd); return
errno; }
for (Virt=mapped_base+(Address&MAP_MASK), Phy=Address;
Phy<Address+NbBytes; Virt+=4*4, Phy+=4*4) {
if (Virt>=mapped_base+MAP_SIZE) { fprintf(stderr,
"Reached page boundary - Stopped\n"); Ret=1; goto Quit; }
switch (Bits) {
case 8:printf("%08x~%08x: %02x %02x
%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x
%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
Phy,
Virt,
(int)*((unsigned char*)Virt+ 0), (int)*((unsigned char*)Virt+ 1),
(int)*((unsigned char*)Virt+ 2), (int)*((unsigned char*)Virt+ 3),
(int)*((unsigned char*)Virt+ 4), (int)*((unsigned char*)Virt+ 5),
(int)*((unsigned char*)Virt+ 6), (int)*((unsigned char*)Virt+ 7),
(int)*((unsigned char*)Virt+ 8), (int)*((unsigned char*)Virt+ 9),
(int)*((unsigned char*)Virt+10), (int)*((unsigned char*)Virt+11),
(int)*((unsigned char*)Virt+12), (int)*((unsigned char*)Virt+13),
(int)*((unsigned char*)Virt+14), (int)*((unsigned char*)Virt+15),
F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
); break;
case 16:printf("%08x~%08x: %04x %04x
%04x %04x %04x %04x %04x %04x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
Phy,
Virt,
(int)*((unsigned short*)Virt+0), (int)*((unsigned short*)Virt+1),
(int)*((unsigned short*)Virt+2), (int)*((unsigned short*)Virt+3),
(int)*((unsigned short*)Virt+4), (int)*((unsigned short*)Virt+5),
(int)*((unsigned short*)Virt+6), (int)*((unsigned short*)Virt+7),
F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
); break;
case 32:printf("%08x~%08x: %08x %08x
%08x %08x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
Phy,
Virt,
*((unsigned int*)Virt+0),
*((unsigned int*)Virt+1),
*((unsigned int*)Virt+2),
*((unsigned int*)Virt+3),
F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
); break;
}
}
Quit:
munmap(mapped_base, NbBytes);
close(memfd);
return Ret;
}
Thanks
--
Guillaume Dargaud
http://www.gdargaud.net/
[toc] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2011-09-23 16:44 +0200 |
| Message-ID | <j5i60u$ftb$1@dont-email.me> |
| In reply to | #10758 |
Guillaume Dargaud wrote: > I know it's frowned upon to post system-specific code here, but I'd like to > know if the error is in my C code (wrong pointer manipulation), in my > handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC > processor). IMO, you'll get better answers in comp.unix.programmer
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-09-23 17:16 +0100 |
| Message-ID | <0.85cb90bd0f5c4eb344da.20110923173028BST.87obybxluj.fsf@bsb.me.uk> |
| In reply to | #10758 |
Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> writes:
> I know it's frowned upon to post system-specific code here, but I'd like to
> know if the error is in my C code (wrong pointer manipulation), in my
> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC
> processor).
I'm going to comment mainly on the C matters. I've no idea about the
rest.
> Basically I get different results when trying to read the memory as a single
> byte, as a short or as an int (the only one that returns correct
> results).
Are you sure the memory content is not changing? Maybe you know what is
to be expected there.
<snip>
> // Note: this is strictly 32-bit code with 32-bit pointers
> // Note 2: only root can use this program
>
> #include <ctype.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <iso646.h>
> #include <errno.h>
>
> #include <fcntl.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <sys/mman.h>
>
> #include <linux/types.h>
>
> static char Str[]="%s [-b|s|w] address [nb]\n"
> "Physical memory dump (using /dev/mem and mmap)\n"
> "-b: byte dump (default)\n"
> "-s: short dump\n"
> "-w: word dump\n"
> "nb: number of values to dump (default 1 which prints 16
> bytes, 8 short or 4 words, must be less than 4kb)\n"
> "Notes: You can use 0x notation for address and nb. Only root
> can access /dev/mem.\n";
>
> #define Usage { fprintf(stderr, Str, argv[0]); return 1; }
>
> // Display printable chars as themselves, or replaces non-printable by '.'
> #define F(ch, offset) ( isprint(*((unsigned char*)(ch)+(offset))) ?
> *((unsigned char*)(ch)+(offset)) : '.' )
In general, a function is preferable to a macro. I'd write both of
these as functions.
> #define MAP_SIZE 4096UL
> #define MAP_MASK (MAP_SIZE - 1)
>
> int main (int argc, char *argv[]) {
> int Bits=8; // 8, 16 or 32
> unsigned int Address=0;
> unsigned int Nb=1, NbBytes;
These are set using strtoul so unsigned long seems like a more natural
type. If you switched to unsigned long long you could probably dispense
with the 32-bit restriction.
> int i, Done=0;
C99 (which you seem to be using) has bool type if for flag variables.
> unsigned int Phy;
> int memfd=0, Ret=0;
> void *mapped_base=NULL, *Virt=NULL;
There's an odd mixture of case in your names. It's not very important
but I can't help trying to work out what the Caps are intended to
convey. If it's nothing, it's clearer to make the variables all look
the same.
> if (sizeof(void*)!=sizeof(int)) {
> fprintf(stderr, "This can run only on 32-bit
> systems with 32-bit pointers\n"); return 1; }
The test does not match the error. If int were anything but 32 bits,
the test would not do what it claims. Maybe
if (CHAR_BIT != 8 || sizeof (void *) != 4)
(The CHAR_BIT test is not really needed since this is POSIX code and
POSIX requires that char has 8 bits.)
> if (argc<2 or argc>4) Usage;
>
> for (i=1; i<argc; i++) {
> if (strcmp(argv[i], "-b")==0) Bits=8;
> else if (strcmp(argv[i], "-s")==0) Bits=16;
> else if (strcmp(argv[i], "-w")==0) Bits=32;
> else if (argv[i][0]!='-') {
> if (Done) {
> if (argv[i][0]=='0' and
> argv[i][1]=='x') Nb=strtoul(argv[i]+2, NULL, 16);
> else Nb=atoi(argv[i]);
strtoul works for the same strings are atoi, and it understands the 0x
prefix so this test does not buy you very much.
> }
> else {
> if (argv[i][0]=='0' and
> argv[i][1]=='x') Address=strtoul(argv[i]+2, NULL, 16);
> else
> Address=atoi(argv[i]);
> Done=1;
Done is too neutral a name for my taste. I'd call it address_arg_seen or
some such thing. I might be tempted to do away with it and use a
pointer to Address which gets switched to point to Nb. Not sure, but I
might.
> }
> }
> }
>
> NbBytes=Bits/8*Nb;
>
> memfd = open("/dev/mem", O_RDONLY);
> if (memfd < 0) { fprintf(stderr, "Can't open /dev/mem: %s\n",
> strerror(errno)); return errno; }
>
> mapped_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, memfd,
> Address & ~MAP_MASK);
> if (mapped_base == (void *) -1) { fprintf(stderr, "Can't map
> the memory to user space: %s\n", strerror(errno)); close(memfd); return
> errno; }
>
> for (Virt=mapped_base+(Address&MAP_MASK), Phy=Address;
> Phy<Address+NbBytes; Virt+=4*4, Phy+=4*4) {
C does not permit arithmetic on void *. Since you want to access bytes,
I'd make the pointers unsigned char * right form the start.
There's no need for 4*4. One 4 is by design (you print in blocks of 4)
but the other is sizeof (void *) and that's both more portable and makes
the intent clearer -- move on by 4 pointers. That won't remove all of
the 32-bitness from the code, but it helps.
> if (Virt>=mapped_base+MAP_SIZE) { fprintf(stderr,
> "Reached page boundary - Stopped\n"); Ret=1; goto Quit; }
Here, the goto is the equivalent of a break. I think break is clearer.
> switch (Bits) {
> case 8:printf("%08x~%08x: %02x %02x
> %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x
> %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
> Phy,
> Virt,
You are playing fast a loose with printf formats and types. Virt is a
pointer and %x is not the right format for that. If you know you want
something more like an integer, convert it. The ideal type is uintptr_t
which has its own format defined in inttypes.h (PRIxPTR).
> (int)*((unsigned char*)Virt+ 0), (int)*((unsigned char*)Virt+ 1),
> (int)*((unsigned char*)Virt+ 2), (int)*((unsigned char*)Virt+ 3),
The int cast is not needed. unsigned char will promote to int.
However, %x expects an unsigned int so a cast to that tye would not be
pointless (though you will get away without it except on malicious
implementations). If Virt is to remain a void *, I'd assign a temporary
const unsigned char *ucp = Virt;
just to be able to write:
ucp[0], ucp[1], ucp[2]
and so on.
> (int)*((unsigned char*)Virt+ 4), (int)*((unsigned char*)Virt+ 5),
> (int)*((unsigned char*)Virt+ 6), (int)*((unsigned char*)Virt+ 7),
>
> (int)*((unsigned char*)Virt+ 8), (int)*((unsigned char*)Virt+ 9),
> (int)*((unsigned char*)Virt+10), (int)*((unsigned char*)Virt+11),
>
> (int)*((unsigned char*)Virt+12), (int)*((unsigned char*)Virt+13),
> (int)*((unsigned char*)Virt+14), (int)*((unsigned char*)Virt+15),
>
> F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
>
> F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
>
> F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
>
> F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
This is crying out for a function. The code is repeated three times.
At the least, I'd factor out the common code:
printf("%08x~%08"PRIuPTR": ", Phy, (uintptr_t)Virt);
switch (Bits) {
}
printf("%c%c%...", F(Virt, 0), F(Virt, 1),...);
rather than repeating it.
> ); break;
> case 16:printf("%08x~%08x: %04x %04x
> %04x %04x %04x %04x %04x %04x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
> Phy,
> Virt,
Again I'd use: const unsigned short *usp = Virt; to be able to write
simpler expressions than those below.
> (int)*((unsigned short*)Virt+0), (int)*((unsigned short*)Virt+1),
>
> (int)*((unsigned short*)Virt+2), (int)*((unsigned short*)Virt+3),
>
> (int)*((unsigned short*)Virt+4), (int)*((unsigned short*)Virt+5),
>
> (int)*((unsigned short*)Virt+6), (int)*((unsigned short*)Virt+7),
>
> F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
>
> F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
>
> F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
>
> F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
> ); break;
> case 32:printf("%08x~%08x: %08x %08x
> %08x %08x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
> Phy,
> Virt,
>
> *((unsigned int*)Virt+0),
>
> *((unsigned int*)Virt+1),
>
> *((unsigned int*)Virt+2),
>
> *((unsigned int*)Virt+3),
>
> F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
>
> F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
>
> F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
>
> F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
> ); break;
> }
> }
>
> Quit:
> munmap(mapped_base, NbBytes);
> close(memfd);
> return Ret;
> }
None of these issues seem likely to explain what you see as wrong but
for that you will have to post somewhere like comp.unix.programmer.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> |
|---|---|
| Date | 2011-09-29 14:53 +0200 |
| Message-ID | <j61po7$1hs$2@ccpntc8.in2p3.fr> |
| In reply to | #10771 |
Thanks for all the comments, I'll do better next time ! The code was a bit of a patch'n'go because it was test code to look into a more complex issue, hence the mix of styles. I'll fix some of the things you mention, though (like the ++ on void*). Anyway the magic smoke came out of our system, so there won't be any more software issues for a while C:-| -- Guillaume Dargaud http://www.gdargaud.net/
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@ieee-dot-org.invalid> |
|---|---|
| Date | 2011-09-23 20:21 -0400 |
| Message-ID | <j5j7qd$pr1$1@dont-email.me> |
| In reply to | #10758 |
On 9/23/2011 9:46 AM, Guillaume Dargaud wrote:
> Hello all,
> I know it's frowned upon to post system-specific code here, but I'd like to
> know if the error is in my C code (wrong pointer manipulation), in my
> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC
> processor).
>[...]
> # ./Peek -w 0x81600001 0x10
> 81600001~48006001: 00000000 00000000 00000000 00000000 ................
> 81600011~48006011: 00000000 00000000 00000000 00000000 ................
> 81600021~48006021: 00000000 00000000 00000000 00000000 ................
> 81600031~48006031: 00000000 00000000 00000000 00000000 ................
In addition to the comments others have offered, it's quite
possible that your processor is unhappy trying to fetch four-byte
integers from odd addresses. Different processors will behave
differently in the face of improper alignment; among the behaviors
I've actually seen are
- The processor traps, and the O/S terminates the program
(often with "SIGBUS" or something like it).
- The processor traps, and low-level code simulates the
invalid operation in software, loading bytes one by one
and assembling the result for you. The program works but
takes a thousand or so times as long as if the access had
been properly aligned.
- The processor handles the load-and-assemble part without a
trap and without software intervention. The program works
but takes two to eight times as long as normal.
- The processor completely ignores the offending low-order
address bits, so when you fetch an int from 0x81600001 you
get the four bytes 0x81600000-0x81600003 instead of the
intended 0x81600001-0x81600004. Peculiar results ensue.
This list is not exhaustive of all possible outcomes; it's
just the outcomes I personally have observed. And it's meant as
a warning that your program is on uncertain ground ...
--
Eric Sosman
esosman@ieee-dot-org.invalid
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2011-09-24 18:26 +0100 |
| Message-ID | <pan.2011.09.24.17.26.53.650000@nowhere.com> |
| In reply to | #10836 |
On Fri, 23 Sep 2011 20:21:31 -0400, Eric Sosman wrote: > - The processor completely ignores the offending low-order > address bits, so when you fetch an int from 0x81600001 you > get the four bytes 0x81600000-0x81600003 instead of the > intended 0x81600001-0x81600004. Peculiar results ensue. The historical ARM behaviour is similar, but with the result rotated such that the byte at the specified address is the least significant byte of the result. IOW, reads use the top 30 bits to determine the address, and the bottom 2 bits to determine the rotation. Byte reads mask the resulting word with 0xFF, word reads don't.
[toc] | [prev] | [next] | [standalone]
| From | Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> |
|---|---|
| Date | 2011-09-29 14:50 +0200 |
| Message-ID | <j61piu$1hs$1@ccpntc8.in2p3.fr> |
| In reply to | #10873 |
I did some tests removing the Linux specific code, and addressing Ptr, Ptr+1, Ptr+4, etc, works as expected (no alignment strangeness). So It must be some weird Linux virtual memory stuff. not relevant to the discussion here. -- Guillaume Dargaud http://www.gdargaud.net/
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2011-09-29 21:57 +0000 |
| Message-ID | <slrnj89qet.1bk.grahn+nntp@frailea.sa.invalid> |
| In reply to | #10836 |
On Sat, 2011-09-24, Eric Sosman wrote: > On 9/23/2011 9:46 AM, Guillaume Dargaud wrote: >> Hello all, >> I know it's frowned upon to post system-specific code here, but I'd like to >> know if the error is in my C code (wrong pointer manipulation), in my >> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC >> processor). Speaking as a C programmer, whatever PPC may do isn't weird. If your code breaks on PPC, it's because it's broken from a language standpoint. >> # ./Peek -w 0x81600001 0x10 >> 81600001~48006001: 00000000 00000000 00000000 00000000 ................ >> 81600011~48006011: 00000000 00000000 00000000 00000000 ................ >> 81600021~48006021: 00000000 00000000 00000000 00000000 ................ >> 81600031~48006031: 00000000 00000000 00000000 00000000 ................ > > In addition to the comments others have offered, it's quite > possible that your processor is unhappy trying to fetch four-byte > integers from odd addresses. > Different processors will behave > differently in the face of improper alignment; among the behaviors > I've actually seen are ... > - The processor handles the load-and-assemble part without a > trap and without software intervention. The program works > but takes two to eight times as long as normal. I'm pretty sure PPC belongs to the "minor slowdown" category. I write PPC code for a living, and treat casts which may cause misalignment as minor bugs, worth fixing if I'm rewriting that part anyway for other reasons. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web