Skip to main content
gamedev.net
🔒 Locked

Reading memory (address space)

Started by blueshogun96 Jun 3, 2010 at 6:52 PM 7 replies 1.4k views
Original Post
blueshogun96
blueshogun96
I hope this isn't too silly to ask, but I'm having trouble reading from the address space in the form of bytes. If you don't understand what I mean, consider this code:

DWORD dwAddress = 0x412FE8;
BYTE var = (BYTE)(*(DWORD*)dwAddress);

This code works in general, but instead of reading that byte only, it reads the next 3 and puts it in a full DWORD! When I try to read the next byte, then Ive already skipped passed three I wanted to read. How do I fix this? Thanks.
Ravyne
Ravyne
Because you're not reading a byte. You're reading a DWORD and then casting the result of the read to a BYTE, which causes it to truncate. Also, you only define a 3-byte pattern.

Try:

BYTE var = *((BYTE*)dwAddress);


On an entirely different matter, are you sticking strictly to C, or are you intending to use C++?

This type of casting is not idiomatic of C++ (nore are the typedefs DWORD, BYTE, etc) -- In C++, you want reinterpret_cast(&dwAddress)


... Actually, and what's more to the point -- you know you can't just go reading from random memory locations, don't you?
throw table_exception("(? ???)? ? ???");
Tntricker
Tntricker
smells of c# with pointers to me. (c/c++ doesn't have a BYTE type)
Yann L
Yann L
Quote:
Original post by Tntricker
(c/c++ doesn't have a BYTE type)

It's a Windows defined data type.
Tntricker
Tntricker
Quote:
Original post by Yann L
Quote:
Original post by Tntricker
(c/c++ doesn't have a BYTE type)

It's a Windows defined data type.


ah, that would explain it then... it would also explain why I don't use them.
blueshogun96
blueshogun96
Quote:
Original post by Ravyne
Because you're not reading a byte. You're reading a DWORD and then casting the result of the read to a BYTE, which causes it to truncate. Also, you only define a 3-byte pattern.

Try:

BYTE var = *((BYTE*)dwAddress);


On an entirely different matter, are you sticking strictly to C, or are you intending to use C++?

This type of casting is not idiomatic of C++ (nore are the typedefs DWORD, BYTE, etc) -- In C++, you want reinterpret_cast(&dwAddress)


... Actually, and what's more to the point -- you know you can't just go reading from random memory locations, don't you?


Okay, the reason I casted to a DWORD* was because I thought by doing so, I'd be chopping off digits in the address (to 0xE8 in this case).

Right now, I'm using C++ even though I'd rather use C. Why am I using C++ and more importantly, why am I reading addresses directly? I'm writing an emulation project involving direct code execution (emulating x86) and I'm catching exceptions using __try and __except. When the exception is caught, I have manually decode the instruction using the address of occurrence given in the exception record structure and emulate it with my own code. Since it doesn't tell me what that instruction is, if it's a read or write, etc. then I have to decode it myself which involves reading that location directly (not writing) assuming it's withing a certain memory range that I personally reserved via VirtualProtect().

Btw, what's the difference between casting with (BYTE*) and reinterpret_cast?
RobTheBloke
RobTheBloke
Quote:
Original post by blueshogun96
Btw, what's the difference between casting with (BYTE*) and reinterpret_cast?


Nothing unless BYTE is typedef'd to something other than unsigned char.

There are 4 casts in C++.
static_cast - the compiler should be able to determine at compile time if it's a valid cast, and you must know at compile time that the cast is always valid.
const_cast - casts away const. If you are using it you are doing something wrong (or interfacing with a legacy API)
dynamic_cast - to be avoided at all costs. Requires that RTTI is enabled when you compile. Lets you upcast from a base class to a derived class, and will return null if not valid. Adds a lot of overhead though.....
reinterpret_cast - for everything else.

The C-style cast is a reinterpret cast with less repetitive strange injury.... C++ Purists prefer it, but ageing programmers such as myself prefer to look after our health ;)
Ravyne
Ravyne
Rob is right that there's no technical difference, however in C++ it is the more idiomatic way of doing things, is the most explicit about what effects are achieved (eg, that same C-style cast can also cast away constness), is consisitant with the other C++ casting mechanisms, and is much easier to do a search for (try writing a search string for C-style casts, unless you know the exact type needed it catches a lot of red-herrings, and good luck trying to search for say, casts which remove constness, leaving aside those that don't)

But, I'd also say that if you're casting enough that the difference between C-style and C++-style casts makes a measurable difference in file-size/RSI-potential in the grand scheme of things, then you're either doing something wrong, or you work directly on the level of bits frequently (compression, networking, embedded). Even still, there are probably better places one could save a few keystrokes. Usually C-style casts seen in C++ code are either from folks that don't know any better, or folks who don't know the difference between the C++-style casts. Niether accusation is directed at Rob specifically, just an observation on coders in general...the old dogs of C... but live and let live I guess, as long as I don't have to deal with their code [grin]


On the utility of const_cast specifically, I've actually run across an interesting use for it, though my case is rather pathologic:

In C++ 0x, the 'auto' keyword was introduced for type inference -- in other words, you just say 'auto' and let the compiler figure the type out by looking at what was assigned to the variable. 'auto' however, doesn't propagate constness (I would imagine it doesn't propagate volatility either).

Recently, I've had to back-port a bunch of C++ 0x code to a pre-C++ 0x compiler that doesn't support the 'auto' keyword. In the application, there were cases where 'auto' was inferring type from a function returning a const-value, and that inferred variable was later modified. Replacing 'auto' with the necessary type, I could not make it 'const' (because it would later be modified), nor could I make it non-const directly, because you can't assign a const value to a non-const variable -- Casting is necessary, and in C++ you use const_cast.

The fact that 'auto' doesn't propate constness was suprising at first, but I guess it makes sense.
throw table_exception("(? ???)? ? ???");
Zipster
Zipster
Quote:
Original post by Ravyne
On the utility of const_cast specifically, I've actually run across an interesting use for it, though my case is rather pathologic:

There's also this more common, less pathological case:
class Foo{public:   Bar& Get_Bar() { return bar; }   const Bar& Get_Bar() const { return const_cast<Foo*>(this)->Get_Bar(); }   // And here be a ton of const and non-const functions that call Get_Barprivate:   Bar bar;};
Replace return bar; with a lot more code that you really don't want to (or rather shouldn't according to DRY) write twice.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.