10

在谷歌做了很多研究后,我发现了这个程序:

#include <stdio.h>

int main()
{
    int val;
    char *a = (char*) 0x1000;
    *a = 20;
    val = *a;
    printf("%d", val);
}

但它会引发运行时错误,在*a = 20.

那么如何读写特定的内存位置呢?

4

9 回答 9

19

您正在这样做,除非在您的系统上您无法写入此内存导致分段错误。

分段错误(通常缩写为 segfault)、总线错误或访问冲突通常是尝试访问 CPU 无法物理寻址的内存。当硬件通知操作系统有关内存访问冲突时,就会发生这种情况。然后操作系统内核向导致异常的进程发送一个信号。默认情况下,接收信号的进程会转储核心并终止。也可以覆盖默认信号处理程序以自定义处理信号的方式。

如果您有兴趣了解更多信息,请在维基百科上查找 MMU。

以下是如何合法地从堆中请求内存。该malloc()函数需要一些字节作为参数来分配。请注意,在您完成使用后,malloc()应通过free()调用同一内存来匹配每个内存。该free()调用通常应与您调用的函数在同一函数中malloc()

#include <stdio.h>
int main()
{
    int val;
    char *a;

    a = (char*)malloc(sizeof(char) * 1);

    *a = 20;
    val = (int)*a;
    printf("%d", val);

    free(a);

    return 0;
}

您还可以通过非常简单的方式在堆栈上分配内存,如下所示:

#include <stdio.h>
int main()
{
    int val;
    char *a;
    char b;

    a = &b;
    *a = 20;
    val = (int)*a;

    printf("%d", val);

    return 0;
}
于 2012-06-26T13:03:40.330 回答
10

这会引发段违规(SEGFAULT),因为您不知道该地址中放入了什么。最有可能的是内核空间,托管环境不希望您随意写入另一个应用程序的内存。您应该只写入您知道您的程序可以访问的内存,否则您将在运行时出现莫名其妙的崩溃。

于 2012-06-26T12:59:49.157 回答
4

如果您在用户空间(您是)中运行代码,那么您获得的所有地址都是虚拟地址而不是物理地址。您不能只假设并写入任何虚拟地址。
实际上,对于虚拟内存模型,您不能仅仅假设任何地址都是有效地址。由内存管理器将有效地址返回给编译器实现,编译器实现将其处理给您的用户程序,而不是相反。

为了使您的程序能够写入地址:

  1. 它应该是一个有效的虚拟地址
  2. 它应该可以访问您程序的地址空间
于 2012-06-26T12:59:12.493 回答
3

你不能随便写任何地址。您只能修改程序可以写入的内存内容。

如果您需要修改某些变量的内容,这就是为什么要使用指针。

char a = 'x';
char* ptr = &a; // stored at some 0x....
*ptr = 'b'; // you just wrote at 0x....
于 2012-06-26T12:59:29.903 回答
2

发出许可后,操作系统将保护内存空间免受随机访问。

你没有指定确切的错误,但我猜你得到一个“ segmentation fault”,这将清楚地表明内存访问冲突。

于 2012-06-26T13:00:33.390 回答
1

您可以写入特定的内存位置。

但只有当您有权写入该位置时。

您得到的是禁止您写入的操作系统0x1000

于 2012-06-26T12:59:11.473 回答
1

这是将数据写入内存位置 0x1000 的正确方法。但是在这个虚拟内存时代,你几乎永远不会提前知道你想要写入的实际内存位置,所以这种东西从来没有被使用过。

如果您能告诉我们您要解决的实际问题,也许我们可以提供帮助。

于 2012-06-26T13:01:44.463 回答
1

您不能随机选择一个内存位置并写入。内存位置必须分配给您并且必须是可写的。

一般来说,您可以获取变量的引用/地址&并在其上写入数据。或者您可以使用 malloc() 请求堆上的空间来写入数据。

该答案仅涵盖如何在内存上写入和读取数据。但是我没有介绍如何以正确的方式进行操作,以便程序正常运行。其他答案可能比我的更好。

于 2012-06-26T13:02:40.467 回答
-1

首先,您需要确定要写入的内存位置。然后,检查您是否有足够的写入权限。

于 2014-11-10T01:45:58.473 回答