Even *MORE* endian issues

Jones
Unregistered
 
Post: #1
Yes, as the title indicates, I'm having even more endian problems. But this time, it's quite un-explainable.

Nothing works anymore! Has my computer become Medium-Endian? Wink

If I do this, for example:

Code:
unsigned int bob = 25;
unsigned short fred = 78;

inline void swapUSHORT(unsigned short swap_this_short)
{
    swap_this_short = (swap_this_short>>8) |
        (swap_this_short<<8);
}


inline void swapUINT(unsigned int swap_this_int)
{
    swap_this_int = (swap_this_int>>24) |
        ((swap_this_int<<8) & 0x00FF0000) |
        ((swap_this_int>>8) & 0x0000FF00) |
        (swap_this_int<<24);
}

swapUSHORT(fred);
swapUINT(bob);

cout << fred << endl;
cout << bob << endl;

Neither value will change. The union method doesn't work either. Come to think of it, it's likely neither of these worked before... but I never tested them in such a fashion either.

Union method:
Code:
short henry;

union {
short a;
unsigned char b[1];
} george, jake;

jake = 72;

george.b[0] = jake.b[1];
george.b[1] = jake.b[0];

henry = george.a;

cout << henry << endl;

That would return 72.

What's going on here? Mad
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
I just ran the code from the second box (with 1 minor change to make it compile) and it prints 18432 Rasp
Quote this message in a reply
Jones
Unregistered
 
Post: #3
Code:
Code:
#include <iostream>

using namespace std;

inline void swapUSHORT(unsigned short swap_this_short)
{
    union {
        short a;
        char b[1];
    } bob, bob2;
    
    bob.a = swap_this_short;
    bob2.b[0] = bob.b[1];
    bob2.b[1] = bob.b[0];
    swap_this_short = bob2.a;
    
}

int main (int argc, char * const argv[]) {
    
    unsigned short fred = 36;
    
    swapUSHORT(fred);
    cout << fred << endl;
    
    return 0;
}

Result:

[Image: holymoly.png]

Annoyed
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #4
char b[1];
should be
char b[2];

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
you're never modifying fred; why do you expect it to change?

In fact, the compiler is perfectly free to optimize away the entirety of your swapUSHORT function Smile
Quote this message in a reply
Jones
Unregistered
 
Post: #6
OneSadCookie Wrote:you're never modifying fred; why do you expect it to change?

In fact, the compiler is perfectly free to optimize away the entirety of your swapUSHORT function Smile

Of course I have! Fred is the argument of the swapUSHORT function, and it gets reassigned. Do you mean it's the "inline" tag causing bad optimization or something?

@Unknown:

Bob is an array of two slots 0 & 1.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #7
@Jones

no its not. you need to change it to char b[2]; for it to have 2 slots.

edit: also yeah, you need to return a value from your endian function or take a pointer as an argument.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Jones
Unregistered
 
Post: #8
unknown Wrote:@Jones

no its not.

edit: also yeah, you need to return a value from your endian function or take a pointer as an argument.

Yeah... just figured that out with some testing. Wacko

Declaring an array like this:

Code:
int example[1];

Means the two available slots are 0 & 1, no? Annoyed
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #9
No, it means you have 1 available slot: 0. When you have an array, you initialize it with the size, and you can access the from 0 to size - 1. (basically, with a total of size slots)

I'm sorry, but if you're having this much trouble with things such as arrays and returning values from functions, I think you should forget about endian issues for now. I think you should probably read through a few tutorials and get to know those two issues (and anything else you're having troubles with) a little better, then in a few days after that, try to tackle the larger subjects. (I'm not saying that you aren't capable of dealing with endian issues, especially since you grasp a lot more than some of the people in my assembly class last year, but regardless of the subject, if you can't adequately express it in code it doesn't matter how much you understand it)
Quote this message in a reply
Jones
Unregistered
 
Post: #10
akb825 Wrote:No, it means you have 1 available slot: 0. When you have an array, you initialize it with the size, and you can access the from 0 to size - 1. (basically, with a total of size slots)

I'm sorry, but if you're having this much trouble with things such as arrays and returning values from functions, I think you should forget about endian issues for now. I think you should probably read through a few tutorials and get to know those two issues (and anything else you're having troubles with) a little better, then in a few days after that, try to tackle the larger subjects. (I'm not saying that you aren't capable of dealing with endian issues, especially since you grasp a lot more than some of the people in my assembly class last year, but regardless of the subject, if you can't adequately express it in code it doesn't matter how much you understand it)

But.. um... why does asking for the final value of an array work then? Huh

I've honestly always done it that way, that's the way I was taught to do it at the classes I took, and it's always seemed to work. I've stopped recently, since most sample code I've seen has done it the *other* way.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #11
If you access element n of a size n array, usually it will work. There is no bounds checking, so it won't crash if you go over unless you're accessing protected memory. As a result, often you can go over the bounds of an array a little bit without ill effect. However, sometimes that memory will be placed right next to a protected section, in which case going even 1 over will cause a crash. Other times, going one over will overwrite another variable you've declared. If you're setting the value of that variable right after, it won't matter, but if you need the previous value, it will, causing unexpected behavior. (which can also result in a crash) Such errors with array access can cause bugs that range from occurring all the time to randomly occurring to rarely or never occurring. The simple programs you've made before probably met the criteria for the last case due to its simple nature and therefore simple memory layout, which is quite unlucky since you never learned from that mistake, or even found out that you made one.
Quote this message in a reply
Jones
Unregistered
 
Post: #12
Heh, wow. I'll keep that in mind.

Thanks! Smile
Quote this message in a reply
Jones
Unregistered
 
Post: #13
This may seem silly, but it's the only source of my (even newer and improved) problem.

Is it possible to swap an int *too* many times and get an incorrect value? The reason I ask this is simple enough.

I'm *still* working on my MD2 loader/displayer. Turns out the reason it failed before was the endian swapper didn't actually swap anything. Heh, funny. Till I realized I'd spent hours trying to figure out the *rest* of the code.Mad

Anyway, from now on I output the contents of my header to see if things have actually been swapped. And it appears to be worked, all the values it says are in the contents of my test md2's header are valid and possible numbers.

But that's not the problem, here is generally how the code works:

1) Read header.
2) Swap header.
3) Read Data.
4) Swap Data.

And it works, *but only the first time* (when I load). When I try to use write the model back out into another file (to see if It read correctly) the data swapping function causes a crash, probably due to EXC_BAD_ACCESS (but that's just a guess, GDB won't tell me Rasp . Here is how the save function is shaped:

1) Swap Header *AND* data.
2) Write header.
3) Swap Header back.
4) Write data.
5) Swap Data back.

Now the *strange* thing is, the swap data function doesn't crash when I open the file, only when I try to write it back out. Annoyed Which means, somewhere along the line the header has become corrupted or something and it's no longer giving the correct values for the number of bytes of certain things (etc...), so I get overflow and bad access errors.

*Can* values be damaged by too much swapping?

Thanks!

EDIT:
GDB gave me a look at the contents of my variables, and although it is known to me to be mistaken sometimes, it shows stuff like "1845559296" for the number of vertices, which is not even valid for an MD2. Or "-536412160" as a size of a chunk in bytes. (Negative bytes? Cool! Are those... "pukes?")

EDIT 2: Heh, writing out this post helped me to spot it... I can't swap both the header *and* the data at once. Wacko
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #14
Are you deciding how many bytes to write after swapping that number back again? That sounds like the most likely explanation.

swap(swap(a)) should be == a.
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #15
To continue the old conversation about why using b[1] didn't cause a crash, here's a general trace of what the program is doing internally:
Code:
1) short henry;

2) union {
short a;
unsigned char b[1];
} george, jake;

jake = 72;

3) george.b[0] = jake.b[1];
4) george.b[1] = jake.b[0];

henry = george.a;

cout << henry << endl;
Code:
For reference, let's pretend this is the chunk
of memory available for your program:
[_______________________]

1) creates space for two bytes:
[__|____________________]
  ^henry, 2 bytes for a short
2) creates space for george and jake:
[__|___|___|____________]
      ^ 3 bytes each, for a 2-byte short and 1-char array
3) george.b[0] is here in memory:
[__|___|___|____________]
      ^
jake.b[1] is here:
[__|___|___|____________]
            ^
4) Likewise, george.b[1] is here:
[__|___|___|____________]
        ^
In each case, b[1] is within your program's chunk of memory, so it does not crash. However, the memory you are accessing does not belong to where you think it does. george.b[1] is actually the first byte of jake's short (a), and jake.b[1] is probably random garbage.

Or, at least that's how I was taught to trace it. Either way, that's why you needed to use b[2] to avoid the problem.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Endian-ness ia3n_g 11 4,083 Sep 20, 2006 11:47 PM
Last Post: OneSadCookie
  Little Endian to Big Endian Jones 42 13,903 Jul 20, 2006 12:07 PM
Last Post: Jones