显示指定地址的 16 个字节的内容(十六进制)
Display contents (in hex) of 16 bytes at the specified 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);
}
但我一直收到 "Segmentation Fault (Core Dumped)" 错误。我试图制作一个虚拟指针来测试
char foo = 6;
char *bar = &foo;
但错误仍然存在
我发现很难解释问题出在哪里,因为您的代码中几乎每一行都是错误的。
我会这样做:
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');
}
需要遍历地址的内容,逐一打印,直到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;
}
输出:
Address 0x7ffe5b86a777: 0677A7865BFE7F000060054000000000
如果您已经有一个指向要打印其内容的地址的指针,您可以将其直接提供给 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
不是指向要打印其内容的内存的指针,那么我不明白它实际上是什么 是 而我需要你最好解释一下。
以上示例代码注意事项:
- 要在不引发未定义行为的情况下使用
%p
,您必须明确地将指针转换为 [const] void *
,除非它已经是 [const] void *
。因为 printf
采用可变数量的参数,编译器不知道其参数的预期类型,所以它不会为您插入此转换,就像采用 [=15= 的普通函数一样] 争论。
- 双重转换
(unsigned int)(unsigned char)
强制从 arguments[i]
读取的 char
被零扩展而不是符号扩展到 unsigned int
的宽度。如果您不这样做,从 0x80 开始的值可能会打印出一堆前导 F(例如 ffffff80
),这可能不是您想要的。
如果在提供的地址处没有 16 字节的可读内存,这仍然会出现段错误。在你的例子中
char foo = 6;
print_16_bytes_at(&foo);
在foo
的地址只能保证有一个字节的可读内存。 (它可能可以在任何您可以轻松获得的计算机上运行,但根据 C 标准的字母,它仍然允许崩溃。)
原始代码存在一些问题。首先,它两次间接传递传入的指针。它将 arguments
视为指向要打印的内容的指针。因为 arguments
是指向 char 的指针,所以这肯定是错误的。 (它最终会从一个非常小的地址读取,这在大多数架构上肯定是分段违规或其他崩溃。)
其次,除非您知道 arguments
指针已正确对齐,否则通过该指针加载 int
可能会由于未对齐的访问而崩溃。 (这很可能会显示为分段违规。)您可能无法假设此例程的正确对齐。
第三,如果您需要打印 16 个字节,那么 int
将(通常)只打印 4 或 8 个字节。使用标准打印例程连接所有片段比逐字节循环更棘手。 (有关此类循环的示例,请参见上面的答案。)
我认为您要么过于复杂,要么没有充分描述实际输入是什么。是指向指针的指针吗?
无论如何,要用一些指向内存的指针以简单的方式完成它,例如你可以这样做(C-like C++,抱歉,在网上匆忙在线完成cpp.sh):
#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);
}
输出:
Address 0x4008e6: 01 0d 00 ff
要打印 16 个字节,只需更改大小参数。
我想不出有 16 个字节的常见类型,所以我不确定你为什么要将它打印为单个数字,通常像上面那样的单字节输出用于调试器(直到用户请求不同尺寸的单位)。
很长一段时间以来,我使用以下函数来打印内存区域的内容:
/*************************************************************/
/**
* 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
关键字。
我正在尝试显示特定地址的内容,为该地址指定一个 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);
}
但我一直收到 "Segmentation Fault (Core Dumped)" 错误。我试图制作一个虚拟指针来测试
char foo = 6;
char *bar = &foo;
但错误仍然存在
我发现很难解释问题出在哪里,因为您的代码中几乎每一行都是错误的。
我会这样做:
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');
}
需要遍历地址的内容,逐一打印,直到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;
}
输出:
Address 0x7ffe5b86a777: 0677A7865BFE7F000060054000000000
如果您已经有一个指向要打印其内容的地址的指针,您可以将其直接提供给 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
不是指向要打印其内容的内存的指针,那么我不明白它实际上是什么 是 而我需要你最好解释一下。
以上示例代码注意事项:
- 要在不引发未定义行为的情况下使用
%p
,您必须明确地将指针转换为[const] void *
,除非它已经是[const] void *
。因为printf
采用可变数量的参数,编译器不知道其参数的预期类型,所以它不会为您插入此转换,就像采用 [=15= 的普通函数一样] 争论。 - 双重转换
(unsigned int)(unsigned char)
强制从arguments[i]
读取的char
被零扩展而不是符号扩展到unsigned int
的宽度。如果您不这样做,从 0x80 开始的值可能会打印出一堆前导 F(例如ffffff80
),这可能不是您想要的。 如果在提供的地址处没有 16 字节的可读内存,这仍然会出现段错误。在你的例子中
char foo = 6; print_16_bytes_at(&foo);
在
foo
的地址只能保证有一个字节的可读内存。 (它可能可以在任何您可以轻松获得的计算机上运行,但根据 C 标准的字母,它仍然允许崩溃。)
原始代码存在一些问题。首先,它两次间接传递传入的指针。它将 arguments
视为指向要打印的内容的指针。因为 arguments
是指向 char 的指针,所以这肯定是错误的。 (它最终会从一个非常小的地址读取,这在大多数架构上肯定是分段违规或其他崩溃。)
其次,除非您知道 arguments
指针已正确对齐,否则通过该指针加载 int
可能会由于未对齐的访问而崩溃。 (这很可能会显示为分段违规。)您可能无法假设此例程的正确对齐。
第三,如果您需要打印 16 个字节,那么 int
将(通常)只打印 4 或 8 个字节。使用标准打印例程连接所有片段比逐字节循环更棘手。 (有关此类循环的示例,请参见上面的答案。)
我认为您要么过于复杂,要么没有充分描述实际输入是什么。是指向指针的指针吗?
无论如何,要用一些指向内存的指针以简单的方式完成它,例如你可以这样做(C-like C++,抱歉,在网上匆忙在线完成cpp.sh):
#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);
}
输出:
Address 0x4008e6: 01 0d 00 ff
要打印 16 个字节,只需更改大小参数。
我想不出有 16 个字节的常见类型,所以我不确定你为什么要将它打印为单个数字,通常像上面那样的单字节输出用于调试器(直到用户请求不同尺寸的单位)。
很长一段时间以来,我使用以下函数来打印内存区域的内容:
/*************************************************************/
/**
* 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
关键字。