是否有办法(只读)访问任意内存位置而不会遇到访问冲突?我认为每个进程都有自己的虚拟地址空间,并且它可以读取所有可用的内存位置......似乎并非如此,因为如果我执行类似
的操作,我的程序会挂起var
IntPtr : PInteger;
AnInteger : Integer;
...
IntPtr := $100;
AnInteger := IntPtr^;
我仍在尝试编写低级递归大小的函数,并尝试检测数据成员是否为对象引用。
谢谢!
答案 0 :(得分:5)
您只能通过指针访问自己的进程内存,即使这样,它也只是为您的进程映射的那些部分。有调试器钩子可以让你访问其他进程内存;但是他们很难做到正确。
因此,如果你真的想要遍历你的进程内存,你可以在这里找到你需要的函数:http://msdn.microsoft.com/en-us/library/ms878234.aspx
Windows中的AFAIR也会将内核的一部分映射到您的进程内存空间(这是没有为您的进程提供所有4G的原因)。
答案 1 :(得分:4)
你的申请挂起了吗?那么你的应用程序有问题。 通常,会有一个简单的AV。 AV导致错误消息。就是这样。
顺便说一下,你不应该害怕它 - 只需处理它。function IsValidObject(const AObj: Pointer { or TObject} ): Boolean;
begin
try
...
// place your checking code there
Result := ...;
except
on EAccessViolation do
Result := False;
end;
end;
我想到的唯一例外是,如果您正在编写某种异常处理程序并想要检测是否存在有效对象。在这种情况下,您可能不希望在异常处理程序中生成异常;)
如果是这种情况 - 那么尝试使用此代码(这是一个示例):
function GetReadableSize(const AAddress: Pointer; const ASize: Cardinal): Cardinal;
const
ReadAttributes = [PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE];
var
MemInfo: TMemoryBasicInformation;
Tmp: Cardinal;
begin
Result := 0;
if (VirtualQuery(AAddress, MemInfo, SizeOf(MemInfo)) = SizeOf(MemInfo)) and
(MemInfo.State = MEM_COMMIT) and (MemInfo.Protect in ReadAttributes) then
begin
Result := (MemInfo.RegionSize - (Cardinal(AAddress) - Cardinal(MemInfo.BaseAddress)));
if Result < ASize then
begin
repeat
Tmp := GetReadableSize(Pointer(DWord(MemInfo.BaseAddress) + MemInfo.RegionSize), (ASize - Result));
if (Tmp > 0) then
Inc(Result, Tmp)
else
Result := 0;
until (Result >= ASize) or (Tmp = 0);
end;
end;
end;
function IsValidBlockAddr(const AAddress: Pointer; const ASize: Cardinal): Boolean;
begin
Result := (GetReadableSize(AAddress, ASize) >= ASize);
end;
但通常你应该选择第一种方法。
答案 2 :(得分:3)
如果你想安全地尝试读取任何内存地址而没有大惊小怪,并且当你想要读取的内存不可访问时,获得一个很好的错误代码而不是异常,你想要使用的函数是在WinAPI中:ReadProcessMemory。
答案 3 :(得分:2)
可能未在所有地址上映射内存。而较低的4kb左右总是受到保护。
但是,如果是VM,如果您控制内存管理器,则可以构建一个包含应用程序映射的所有内存范围的列表。
答案 4 :(得分:1)
除非有一些我不知道的魔法方式,否则我很确定你不能这样做。 Windows使用受保护的内存,这意味着您无法访问未专门分配给您的任何内容。
有DMA,但它保留给驱动程序级软件。
答案 5 :(得分:1)
在旧的Windows,95,98,Me中你可以在你的函数中做一些内联asm并读/写一些任意的内存位置或硬件端口......
函数ReadPortByte:Byte; VAR 基地:Word; 开始 基数:= FAddress; ASM mov DX,Base 在AL,DX mov Result,AL 结束; 端;
您仍然可以使用设备驱动程序执行此操作,但Vista可能会导致一些问题,除非为Vista及更高版本正确编译驱动程序。
有几个免费的,值得尝试。
约翰