取消引用双级指针会导致取消引用单级指针的不同行为

时间:2013-04-27 19:41:00

标签: c++ pointers reverse-engineering memory-editing

版本1:

int* work(int** pointer, int offset)
{
    return *pointer + (offset/sizeof(int));
}

int main()
{
    int** pointer = (int**) 0x4df73c;
    int offset = 0xf4;

    int* healthLowestPointer = work(pointer, offset);

    while(true) {
        *healthLowestPointer = 1000;
        Sleep(250);
    }
}

第2版:

int* work(int* pointer, int offset)
{
    return (int*) (*pointer + (offset/sizeof(int)));
}

int main()
{    
    int* pointer = (int*) 0x4df73c;
    int offset = 0xf4;

    int* healthLowestPointer = work(pointer, offset);

    while(true) {
        *healthLowestPointer = 1000;
        Sleep(250);
    }
}

版本1正常工作,但版本2似乎没有。我不明白为什么版本2被破坏了。是不是取消引用双级指针与取消引用单级指针相同,即它抓取指针包含的内存地址的值?

如何编写一个以n级指针作为输入的函数,并通过解除引用n级指针n-1次返回1级指针?

2 个答案:

答案 0 :(得分:2)

他们是非常不同的东西。 int**是指向int的指针。如果您取消引用它,则会得到int*int*是指向int的指针。如果您取消引用它,则会得到int

在第一个示例中,您将值int**的{​​{1}}作为0x4df73c的第一个参数传递。然后你取消引用它,这应该给你一个work。也就是说,int*是地址的地址,而0x4df73c让你成为第二个地址。然后通过添加*pointer对此int*进行指针运算,计算出(offset/sizeof(int))个字节的intoffset。因此,当您添加此值时,int*将移动到指向该偏移处的int。然后返回此int*,一切顺利。

在第二个示例中,您将0x4df73c作为int*传递。然后你取消引用它,它会给你一个int。现在+不做指针算术 - 它做整数运算。 (offset/sizeof(int))仍会以int个字节为您提供offset s的数量,但算术将无法执行您想要的操作。它不会将int的值增加适当的数量。

假设您的计算机上int为4个字节。当您int*被称为pp + 5时,5只会将p添加到5中的地址。它会增加int({1}}(20个字节)大小的int倍,因此它现在指向第5个int。但是,如果您有一个名为i的{​​{1}}而i + 5,那么这只会添加5

这就是你的问题。当您添加到int时,您没有进行适当的算术。我认为如果你把它更改为工作,假设你的系统int*int大小相同(正如你所说的那样):

return (int*) (*pointer + offset);

但我不推荐此。不要使用int,就好像它是指针一样。 (int*)的演员阵容涉及reinterpret_cast并且非常糟糕。坚持你的第一个代码。

答案 1 :(得分:0)

指针算术和整数运算不是一回事。

忽略写入您正在使用的位置是否有效的问题,请考虑以下结果:

int i=5;
int j=i+1; // now j==6
int* pi = &i; // let's say pi is 0x1000
int* pj = &i+1 // now pj is 0x1000 + (sizeof int)