访问特定的内存地址

时间:2013-12-12 16:17:12

标签: c memory-management

我是一名新的C程序员,仍在学习语言本身。

无论如何 - 我正在尝试访问特定的内存地址。

我写了这段代码:

#include <stdio.h>

int main()
{
    int* p = (int*) 0x4e0f68;
    *p = 12;
    getchar();
}

当我尝试访问这样的特定内存地址时,程序崩溃了。

我不知道这些信息是否相关,但我使用的是Windows 7和Linux Ubuntu  (我在Windows 7上尝试过这段代码)。

程序崩溃的原因有何解释? 如何访问特定的内存地址(编译时已知的地址,我不是指动态内存分配)?

感谢。

4 个答案:

答案 0 :(得分:3)

你不拥有并且访问它的内存是未定义的行为。任何事情都可能发生,包括崩溃。

在大多数系统上,你可以检查内存(虽然技术上仍然是未定义的行为),但写一个完全不同的故事。

答案 1 :(得分:3)

严格来说,你不能像这样创建一个有效的指针。有效指针必须指向有效对象(在堆栈上或从malloc获得)。

对于大多数现代操作系统,您有一个只有您的进程才能看到的虚拟内存空间。当您从系统请求更多内存(mallocVirtualAllocmmap等)时,此虚拟内存将映射到可以安全读取和写入的实际可用内存中。所以你不能只是采取任意地址,并尝试在没有OS合作的情况下使用它。

Windows的一个例子:

#include <windows.h>
#include <stdio.h>

int main(void)
{
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    unsigned pageSize = sysinfo.dwPageSize;
    printf("page size: %d\n", pageSize);

    void* target = (void*)0x4e0f68;
    printf("trying to allocate exactly one page containing 0x%p...\n", target);
    void* ptr = VirtualAlloc(target, pageSize, MEM_COMMIT, PAGE_READWRITE);

    if (ptr)
        printf("got: 0x%p\n", ptr); //   ptr <= target < ptr+pageSize
    else
        printf("failed! OS wont let us use that address.\n");

    return 0;
}

请注意,这会在不同的运行中为您提供不同的结果。不止一次尝试。

答案 2 :(得分:0)

只是为了克服OP写的一个短语:严格来说,编译时不知道与程序(代码或数据)相关的地址。程序通常在OS确定的任何地址加载。程序看到的最终地址(例如,读取全局变量)由OS在程序代码中使用某种重定位表进行修补。由程序调用的DLL函数具有类似的机制,其中可执行文件的IDATA部分被转换为跳转表,以跳转到DLL中函数的实际地址,从内存中获取DLL中的实际地址。

也就是说,如果程序没有重定位信息,那么确实可以预先知道变量将放在哪里。这在Windows中是可行的,您可以告诉链接器将程序加载到绝对虚拟地址。如果可能,OS加载程序将尝试将程序加载到该地址。

但是,不建议使用此功能,因为它可能导致轻松利用可能的安全漏洞。如果攻击者在程序中发现安全漏洞并尝试向其中注入代码,那么如果程序在特定地址中具有所有变量和函数,则对他来说会更容易,因此恶意代码将知道在何处制作补丁以获得控制权该计划。

答案 3 :(得分:0)

您所获得的是一个段错误 - 当您尝试访问内存时,您无权访问。指针,至少对于用户空间,必须指向一些变量,对象,函数等。您可以使用&amp;设置指向变量的指针。 operator - int* somePtr = &variableToPointTo,或另一个指针 - int* someNewPtr = somePtr。在内核模式(环0)或OS开发中,您可以这样做,但不建议这样做。在MS-DOS中,你可能会破坏你的机器,因为没有针对它的保护。