取消自定义内存地址(C)时出现段错误

时间:2018-09-16 17:51:10

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

我想声明一个指针,让它拥有一个自定义地址,然后为其分配一个值:

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值的尝试不会编译。

第三个假设是这样的地址必须不可用,但这也没有道理,因为无论我给出的地址还是pointer的类型,第4行始终有效。

3 个答案:

答案 0 :(得分:6)

  

第三个假设是该地址必须不可用

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

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

  

但这还是没有道理的,因为无论我给出的地址还是指针的类型,第4行始终有效。

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

区别类似于“您可以打印地址吗?” (例如“ 123 Main Street,SomeTown和SomeCountry”)和“您可以在该地址输入房屋吗?” (以上地址不可能,因为地球上没有“ SomeCountry”)。即使该地址有效,例如“ 1600 Pennsylvania Ave NW,Washington,DC 20500”,您可能仍然无法输入。

答案 1 :(得分:2)

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

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

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

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

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

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

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

答案 2 :(得分:0)

写到任意内存地址是危险的,现代操作系统不允许这样做,最好创建一个内存Blob并对其进行写入。

例如使用malloc:

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