知道是否可以检索内存地址的值

时间:2016-06-06 12:06:58

标签: c++ windows

我正在尝试将值存储在计算机的内存地址中。为此,我编写了一个小的C ++程序,但在尝试获取存储在地址0x1中的值时,它会引发读访问冲突错误。

这里的目标是获取可以检索的值,而不是那些不能检索的值。

无论如何,这是代码:

#include <iostream>
#include <conio.h>

using namespace std;

int main() {
    unsigned long long *ptr1;
    for (unsigned long long i = 0; i < 0xFFFFFFFF; i++)
    {
        try {
            ptr1 = reinterpret_cast<unsigned long long*>(i);
        }
        catch (...) {
            cout << "Some erros happened" << endl;
        }

        if (ptr1 != nullptr) {
            try {
                cout << "Value in address 0x" << i << ": " << *ptr1 /*Error here*/ << endl;
            }
            catch(...) {
                cout << "Some erros happened" << endl;
            }
        }
        else {
            cout << "Value in address 0x" << i << ": null pointer" << endl;
        }

    }
    _getch();
    return 0;
}

请注意,在 for 循环的第一次迭代中,程序检测到 ptr1 空指针,但在第二次迭代中,程序在到达 * ptr1 时崩溃。

如果我没有弄错的话,我认为错误来自 * ptr1 无法读取存储在该地址中的内容,但我不知道如何在不实际引用的情况下知道 PTR1

显然,在这种情况下不能使用try catch块。

顺便说一下,这是程序的输出:

Value in address 0x0: null pointer Value in address 0x1:

然后它抛出错误。

3 个答案:

答案 0 :(得分:3)

从C ++标准的角度来看,没有任何技术可以合法地完成。根据标准,知道可以访问内存位置的唯一方法是确保它已分配给您的程序。换句话说,您的指针需要指向一个全局/静态/局部变量的地址,或者使用malloc函数分配的块。

所有其他地址都是您的计划的禁区。如果您访问它们,系统可以执行任何操作,从返回无效值到终止程序。

答案 1 :(得分:0)

来自此for (unsigned long long i = 0; i < 0xFFFFFFFF; i++)

for loop您似乎正在尝试访问流程的完整虚拟地址空间。

因此,您可以首先查找正在使用的页面大小。然后你可以尝试锁定该页面。 Windows中提供了一些API。根据结果​​,您将了解哪个地址范围受限制。

VirtualLock function

答案 2 :(得分:0)

我玩弄信号并抓住#include <stdio.h> #include <signal.h> #include <setjmp.h> #include <conio.h> jmp_buf jumpBuffer; void sig(int ignore) { signal(SIGSEGV,sig); //to prevent reseting signal action back to SIG_DFL (default) longjmp(jumpBuffer,1); //jump back to setjmp() and correct our mistakes } int main() { signal(SIGSEGV,sig); unsigned int a = 0x123456; unsigned int b = 0x876543; printf("a (%x) resides at %p \n",a,&a); printf("b (%x) resides at %p \n",b,&b); getch(); static const long max = 0xFFFFFFFF; int *i = 0; //This is tricky, null pointer constant doesn't need to be represented as zero for (;(long)i < max;i++) //these pointer-to-integer casts are also implementation-specific { //if jmp was made to setjmp, returned value is specified as second parameter in longjmp //if this is regular call, not jump, returned value is zero if (setjmp(jumpBuffer) == 0) printf("Address %p contains %x \n",i,*i); //if this fails, SIGSEGV is raised and sent to our handler else printf("Address %p is invalid \n",i); } } 。请注意,这个例子非常(我再次说,非常)坏例子,它甚至不合法(就C(++)标准而言),但它只是工作™。我用2(局部)变量测试它,似乎工作。

另外,请勿忘记此在您的(物理)内存中打印打印值。通常,您的程序会获得虚拟地址空间,其中虚拟地址不必与物理地址匹配。因此,您不会看到其他进程的内存地址内容,您只会看到自己的内容。

SparePart