【问题标题】:How to loop and read content from a range of memory address如何从一系列内存地址循环和读取内容
【发布时间】:2015-08-03 02:43:44
【问题描述】:

我是 C 新手,我想从内存地址范围内读取内容

假设我有以下地址范围:0x00065580 - 0x000655c0

此范围从命令获取:

 $ cat /proc/a_process_pid/maps | grep heap
 00065580-000655c0 ...........heap

(请查看上述范围内的十六进制转储图像)

我尝试使用循环但没有运气,(就像 Java 开发人员的想法)

#include <stdio.h>
#define START_ADDR 0x00065580 
#define END_ADDR 0x000655c0
int main(){
   char *start = START_ADDR ;
   char *end = END_ADDR;
   for( char *i=start ; i <= end ; i++ ){
        printf("%s",i);
   }
   return 0;
}

它会产生错误:

root@localhost:~# ./test
Segmentation fault (core dumped)

请告诉我我做错了什么以及我需要了解什么?

【问题讨论】:

  • 是test你的源代码文件名吗?你可能正在编译你的可执行文件,
  • 对不起,我以错误的方式运行程序,我编辑了错误,只是简单的“分段错误(核心转储)”
  • printf("%s",*i); 不是吗?
  • 你从哪里得到这些地址值的?是什么让您相信这些地址实际上在您的进程内存空间中包含有效内存?

标签: c memory-address


【解决方案1】:

现代操作系统使用virtual memory:一个进程看到的内存地址与物理地址不同,程序通常不能接触到另一个进程拥有的内存。您似乎正在查看来自一个特定进程的内存转储,但地址 0x00065580 实际上确实对应于不同的物理地址,例如0x00123456。在您自己的程序中,地址0x00065580 将对应于另一个物理地址,例如0x00589263。操作系统将确保其他程序使用的任何物理地址都不会被您的访问。

如果您的进程以root身份运行,您可以use system calls to indirectly access other processes' memory

【讨论】:

  • 谢谢Aasmund,我知道程序正在使用虚拟内存,我只想从中读取。我可以从虚拟内存中读取吗?
  • 也许简要介绍一下从 真实模式 计算到 保护模式 计算的转变历史有助于加深理解。
  • @Ryo:关键是一个进程(一个正在运行的程序)只能从它自己的虚拟内存中读取,而不能从另一个进程的虚拟内存中读取。并且操作系统不会让您的进程访问另一个进程的虚拟内存映射到的物理内存(除非您的进程专门请求共享内存)。
  • 我需要从中读取内存的进程是一个GT.M数据库进程,它使用共享内存段tinco.pair.com/bhaskar/gtm/doc/books/ao/UNIX_manual/apas01.htm。我有机会吗?
  • @Ryo:该页面提到由mmapshmat 创建的共享内存段。在这两种情况下,共享内存段的地址在两个进程中可能会不同,并且您无法根据内存地址访问它。对于mmap,您需要为正在运行的程序用于其内存映射的同一文件指定文件描述符;对于shmat,您需要该特定共享内存段的标识符。
【解决方案2】:

这是一个 C++ 程序,它将阐明如何打印特定内存位置的地址(或数据)。

#include<iostream>
using namespace std;
int main()
{
    int* arr = new int[10];
    int *start = NULL;
    int *end = NULL;

    for(int i=0;i<10;i++)
        arr[i] = i+1;
    start = arr;
    end = &arr[9];
    for(int *start=arr;start<end;start++)
        cout<<"  "<<start;
    cout<<endl;
    system("PAUSE");
    return 0;
}

我在您粘贴的代码中没有发现任何问题。但问题在于 START 和 END,即您在程序中使用的地址的位置。这些位置不包含该进程的任何有效内存,因此您强制要求从一些垃圾内存空间读取数据,从而导致 SEGFAULT。希望这会有所帮助。

【讨论】:

  • 您的回答有两个问题:首先,它是 C++ 代码,并且 OP 标记了 C,而不是 C++。第二:OP的代码确实存在问题:他试图打印指针的内容,就好像它们是字符串一样。
  • 这意味着我只能从我的程序使用的内存地址中读取,而不能访问另一个进程的内存?
  • @Ryo 您的程序将在用户模式下运行,您肯定无法访问其他进程的内存。进程的内存访问限制是它自己分配的内存。如果您确定它是您的进程的有效内存地址,则可以访问特定内存。 unsigned int* ptr = (unsigned int*) 0xffef8016,我再说一遍,如果 0xffef8016 是您的进程的有效内存地址,这是可能的。
  • 我看到 Linux 有 ptrace() 函数来跟踪另一个进程,这可以在我的情况下使用吗?
  • 我尝试使用 ptrace ,但它在跟踪期间休眠另一个进程,它不适合我的情况
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-09
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多