如何更改存储在内存地址的值

时间:2013-12-03 14:33:06

标签: c pointers memory

我尝试修改存储在某个内存地址的值。

地址存储在某个指针中,但用新的int改变它会改变内存地址(当然)。

int *toModify = (int *)(foo+5); //foo is a adress of a function. 
//The val to alter is 5bytes after it
int newVal = 5;
toModify = &newVal;


//implementation of foo
int foo(){
return 42;
}

让我们说toModify有价值42.我想把它改为5。 如何在toModify的地址中存储更改?

6 个答案:

答案 0 :(得分:3)

您无法以符合标准的便携式方式执行此操作。即使您希望以非可移植的方式执行此操作(您可以通过直接操作机器代码来执行此操作),foo可能在只读内存中,因此无法修改。

最好定义foo来访问可以更改的全局变量或静态变量。例如:

static int n = 42;

int foo() {
    return n;
}

// when you want to modify it
n = 5;

答案 1 :(得分:1)

而不是

toModify = &newVal;

使用

*toModify = 5;

答案 2 :(得分:1)

假设foo是函数的名称,那么首先执行此操作:

int *toModify = (int *)((char *) foo + 5);

首先将foo从指向函数的指针转换为指向char的指针。这允许您将其作为指针使用。通常,您不能使用指向函数的指针执行算术运算,因此您需要一个指向对象类型的指针。 C标准不保证此转换将起作用,因此您必须确保C实现支持它。

我们将其转换为指向char的指针,以便添加五个字节,而不是五个字节的另一个对象类型。然后我们将总和转换为指向int的指针,以便将其分配给toModify

然后这样做:

int newVal = 5;
memcpy(toModify, &newVal, sizeof newVal);

这会尝试将值为{的int复制到toModify指向的位置。这避免了尝试直接使用*toModify = 5;分配值时的一个问题,即分配将字节置为违反C标准规则的别名,因此行为不是由标准定义的,尽管它可能是一些C实现支持。但是,它还有其他问题。

首先,程序可能无法写入此地址的字节数。现代操作系统通常使用内存保护来防止代码被不正确地修改,这种保护会导致memcpy失败。

其次,即使字节是可写的并且memcpy修改它们,也不能保证执行指令的处理器部分会看到它们。指令流中的字节通常由现代处理器缓存,并且更改内存中的字节不会更改缓存中的字节。通常,必须执行特殊指令来刷新指令缓存。执行此操作的方法取决于目标处理器和操作系统。

如果您这样做是为了尝试修改代码只是作为一种学习练习,除非您在支持此功能的特殊嵌入式环境中工作,否则这不是正确的方法。如果你出于另一个原因试图这样做,你几乎肯定应该放弃它并寻求另一种方法。

答案 3 :(得分:0)

Perreal的(删除)答案是正确的:

*toModify = newVal;

...但是......你正在尝试在应用程序的代码空间中编写代码,现代操作系统会竭尽全力阻止这种情况,因为这是主要的安全风险。这可能就是你可能会遇到分段错误的原因。

另外,你在一个地址(foo+5)上写了一个int(你的系统可能是一个4字节的值?),它没有与4字节边界对齐。同样,您的硬件可能不支持此功能,

如果你想修改一个字节,你需要这个。

char * toModify; 

答案 4 :(得分:0)

代码在unix上通常是只读的。它通常在嵌入式系统上是只读的,因为它实际上位于闪存中。

在UNIX上,您可以使用ptrace()和PTRACE_POKETEXT来解决这个问题。

答案 5 :(得分:0)

我通过修改存储在mprotect中的值存储页面来解决它。然后你可以访问该地址并写信给它

相关问题