在指定地址显示16字节的内容(十六进制)

时间:2017-10-01 15:31:51

标签: c++ c pointers hex memory-address

我试图显示特定地址的内容,给定该地址的char *。到目前为止,我尝试使用以下实现

int mem_display(char *arguments) {
    int address = *arguments; 
    int* contents_pointer = (int*)address;
    int contents = *contents_pointer;
    printf("Address %p: contents %16x\n", contents_pointer, contents);              
}

但我一直得到一个"分段错误(Core Dumped)"错误。我试图制作一个虚拟指针来测试

char foo = 6;  
char *bar = &foo;

但错误仍然存​​在

6 个答案:

答案 0 :(得分:5)

我发现很难解释问题是什么,因为代码中几乎每一行都是错误的。

这就是我要做的事情:

void mem_display(const void *address) {
    const unsigned char *p = address;
    for (size_t i = 0; i < 16; i++) {
        printf("%02hhx", p[i]);
    }
    putchar('\n');
}

答案 1 :(得分:2)

您需要迭代地址的内容,并分别打印每个内容,直到达到16.示例代码:

#include <stdio.h>

void mem_display(unsigned char *arguments) {
    printf("Address %p: ", arguments);
    int i =0;
    unsigned char* byte_array = arguments;
    while (i < 16)
    {
        printf("%02hhx", byte_array[i]);
        i++;
    }            
}

int main(void) {
    unsigned char foo = 6;  
    unsigned char *bar = &foo;
    mem_display(bar);

    return 0;
}

输出:

  

地址0x7ffe5b86a777:0677A7865BFE7F000060054000000000

答案 2 :(得分:2)

如果您已经有一个指向要打印内容的地址的指针,您可以直接将其提供给printf,如下所示:

void print_16_bytes_at(const char *arguments)
{
   printf("Address %p: contents", (const void *)arguments);
   for (int i = 0; i < 16; i++)
       printf(" %02x", (unsigned int)(unsigned char)arguments[i]);
   putchar('\n');
}

如果arguments没有指向要打印内容的内存,那么我就不明白它实际上是什么 我需要你更好地解释。

以上示例代码的注释:

  1. 要使用%p而不引发未定义的行为,您必须明确地将指针强制转换为[const] void *,除非它已经是[const] void *。因为printf接受可变数量的参数,所以编译器不知道其参数的预期类型,因此它不会为您插入此转换,就像使用带{{{}的普通函数一样。 1}}参数。
  2. 双重演员[const] void *强制(unsigned int)(unsigned char)char读取的内容为零扩展,而不是符号扩展为arguments[i]的宽度。如果你不这样做,那么从0x80开始的值可能会打印出一堆领先的F(例如unsigned int),这可能不是你想要的。
  3. 如果在提供的地址上没有16字节的可读内存,这仍然会出现段错误。在你的例子中

    ffffff80

    只保证char foo = 6; print_16_bytes_at(&foo); 地址的可读内存的一个字节。 (它可能适用于您可以轻松获得的任何计算机,但它仍然允许按照C标准的字母崩溃。)

答案 3 :(得分:1)

原始代码存在一些问题。首先,它将传递的指针指向两次。它将arguments视为指向要打印内容的指针。由于arguments是指向char的指针,因此这绝对是错误的。 (它最终将从一个非常小的地址读取,这是一个明确的分段违规或大多数架构上的其他崩溃。)

其次,除非您知道arguments指针已正确对齐,否则通过该指针加载int可能会因未对齐的访问而崩溃。 (这可能会显示为分段违规。)您可能无法假设此例程正确对齐。

第三,如果你需要打印16个字节,那么int(通常)只会得到4个或8个字节。使用标准打印例程来连接所有部分比逐字节循环写入更加棘手。 (有关此类循环的示例,请参阅上面的答案。)

答案 4 :(得分:1)

我认为你要么过于复杂,要么你没有足够的描述实际输入是什么。它指向指针吗?

无论如何,要用一些指向内存的指针以简单的方式做到这一点,你可以像这样做(C-like C ++,抱歉,在web cpp.sh网上快点完成):

<your.package.name.ExtendedBottomNavigationView android:id="@id/bottomMenu" style="@style/bottomMenu"/>

输出:

#include <iostream>

const unsigned char fakeData[] = { 1, 13, 0, 255 };

void mem_display(
    std::FILE* file,
    const unsigned char* memoryPtr,
    const size_t size)
{
    fprintf(file, "Address %p:", (const void*)memoryPtr);
    for (size_t i = 0; i < size; ++i) fprintf(file, " %02hhx", memoryPtr[i]);
    fprintf(file, "\n");
}


int main()
{
    mem_display(stdout, fakeData, 4);
}

要打印16个字节,只需更改size参数。

我不能想到具有16个字节的普通类型,所以我不确定为什么要尝试将其打印为单个数字,通常在调试器中使用如上所述的单字节输出(直到用户请求不同大小的单位)。

答案 5 :(得分:0)

很长一段时间我都使用以下功能打印内存区域的内容:

/*************************************************************/
/**
  * Function to dump memory area
  * \param address     start address
  * \param len         length of memory area
  */
/*************************************************************/
void dump( void* address, int len ) noexcept{
    int i;
  printf("dump from 0x%lX (%d bytes)\n",(long)address, len);
  printf("=============================================");
  for(i=0; i<len; i++){
    if(i%16==0){printf("\n");}
     printf("%2X ",(*((char*)address+i))&0xFF);
  }
  printf("\n=============================================\n");
}

对于C程序,请删除noexcept关键字。