我正在尝试将值存储在计算机的内存地址中。为此,我编写了一个小的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:
然后它抛出错误。
答案 0 :(得分:3)
从C ++标准的角度来看,没有任何技术可以合法地完成。根据标准,知道可以访问内存位置的唯一方法是确保它已分配给您的程序。换句话说,您的指针需要指向一个全局/静态/局部变量的地址,或者使用malloc
函数分配的块。
所有其他地址都是您的计划的禁区。如果您访问它们,系统可以执行任何操作,从返回无效值到终止程序。
答案 1 :(得分:0)
for (unsigned long long i = 0; i < 0xFFFFFFFF; i++)
的 for loop
您似乎正在尝试访问流程的完整虚拟地址空间。
因此,您可以首先查找正在使用的页面大小。然后你可以尝试锁定该页面。 Windows中提供了一些API。根据结果,您将了解哪个地址范围受限制。
答案 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