【问题标题】:Segfault when dereferencing a custom mem address (C)取消引用自定义 mem 地址时的段错误 (C)
【发布时间】:2019-02-20 17:41:41
【问题描述】:

我想声明一个指针,让它持有一个自定义地址,然后给它赋值:

void main()
{
    char *ptr;
    ptr = (char *)0x123123; //the assignment works perfectly with a cast
    printf("%p\n", ptr); //and the pointer indeed holds the address it's supposed to
    *ptr = 'a'; //but this breaks
    puts("2");
}

最初我认为原因是因为我试图取消引用未初始化的内存。但我实际上怀疑是不是这种情况,因为这个some_type *some_ptr = &some_variable; 完美无缺,所以这笔交易必须是我分配给它的地址。

然后我想,同样3'a'"alpine"是常量,(char *) 0x123123也必须是常量。 const-s 不能在 C 中编辑,但仍然不能这样,因为尝试更改 const 值将无法编译。

第三个假设是这样的地址一定不可用,但这也没有意义,因为第 4 行始终有效,无论我提供的地址或 pointer 的类型如何。

【问题讨论】:

  • 你想做什么?你不能只写内存中的随机地址。
  • 你怎么知道你的程序实际上拥有那个随机地址?每个进程都可以写入操作系统给定的内存位置。您不能将任意内容写入内存中的任意位置。
  • @tkausl 这正是我想要做的。
  • @eozd 在这种情况下,是否有可能找出操作系统将提供给程序的地址范围?它是否至少在理论上可以保证,写入该范围内的随机地址不会中断?
  • 不能用mprotectvirtualprotect/virtualquery给内存读写权限,然后再写入,重置内存保护吗?

标签: c pointers memory segmentation-fault memory-address


【解决方案1】:

OP 在其他地方澄清说,这实际上是一个 XY 问题。

X 问题:读取/写入任意内存位置。

Y 问题:实现一个使用连续内存的链表。

当然,答案是:必须实现自己完整的内存管理系统才能到达那里。

如:首先,您使用malloc() 获取大块连续内存。然后你可以使用任意指针该内存块。但当然,您的 代码必须跟踪哪些地址已被使用。或者在列表节点被删除时正确“释放”。

棘手的部分是处理极端情况,例如:当你的最后一个“指针”用完时会发生什么?您是否 malloc() 更大的区域,并移动内存中的所有数据?

最后:假设您管理的不是一块内存,而是一个数组。 (链表的实现通常基于数组,因为这让一些事情变得更容易)

【讨论】:

    【解决方案2】:

    写入某个任意内存地址是危险的,现代操作系统不允许这样做,最好创建一个内存 blob 并写入该地址。

    例如使用 malloc :

    ptr = malloc(32); // now you can write to this memory block and it perfectly legal
    *ptr = 'a';
    

    【讨论】:

      【解决方案3】:

      第三个假设是这样的地址一定不可用,

      这是正确的:在现代操作系统(都有内存保护)上,您不能写入任意内存地址。

      过去可以访问不使用虚拟内存的操作系统上的任何内存(例如 MS-DOS),但允许这样做通常是一个非常糟糕的主意——它允许随机程序破坏操作系统状态,并且需要非常频繁地重新启动。

      但这也没有任何意义,因为第 4 行始终有效,无论我给出的地址或指针的类型如何。

      您混淆了两种不同的操作:打印地址(无论该地址是什么都允许)和取消引用地址,即读取或修改存储的值地址(仅允许有效地址)。

      区别类似于“你能打印地址吗?” (例如“123 Main Street, SomeTown, SomeCountry”)和“你能进入那个地址的房子吗?” (上述地址不可能,因为地球上没有“SomeCountry”)。即使地址是有效的,例如“1600 Pennsylvania Ave NW, Washington, DC 20500”,您可能仍然无法进入。

      【讨论】:

      • 我真的很喜欢与邮政地址的比较。虽然,当然,你一定是在开玩笑:一个有你昵称的人……你只要联系普京先生,你就可以进入华盛顿所说的地方。 ;-)
      猜你喜欢
      • 2022-12-14
      • 1970-01-01
      • 2020-03-20
      • 2023-03-26
      • 2018-12-09
      • 2013-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多