取消引用自定义mem地址时的Segfault(C)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了取消引用自定义mem地址时的Segfault(C)相关的知识,希望对你有一定的参考价值。

我想声明一个指针,让它保存一个自定义地址,然后为其赋值:

void main()
{
    char *ptr;
    ptr = (char *)0x123123; //the assignment works perfectly with a cast
    printf("%p
", 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的类型。

答案

第三个假设是这样的地址必须是不可用的,

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

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

但这也没有意义,因为第4行总是工作,无论我给出的地址或指针的类型。

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

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

另一答案

OP在别处澄清,这实际上是一个XY问题。

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

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

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

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

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

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

另一答案

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

例如使用malloc:

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

以上是关于取消引用自定义mem地址时的Segfault(C)的主要内容,如果未能解决你的问题,请参考以下文章

从Assembly调用C函数(printf)时的Segfault

在 Objective C 中为自定义类实现委托时的引用计数

cppcheck : 可能的空点取消引用

程序退出时的 Segfault (-11)

通过指针、强制转换和取消引用加载向量?

创建 avx 向量时的 Segfault