我正在尝试创建一个小程序,它接受一个物理内存地址并打印存储在该位置的数据。我向程序传递两个参数-地址和我想要打印的内存大小(以字节为单位)。
问题出在当我传入的地址值超过一定值时,strtol()函数就会输出一个无意义的值。下面是代码:
如果运行以下命令,将获得期望的值。
然而,如果我更改输入地址,该值会与预期值不同:
问题出在当我传入的地址值超过一定值时,strtol()函数就会输出一个无意义的值。下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <asm-generic/fcntl.h>
#include <unistd.h>
int main(int argc, char** argv)
{
unsigned int mem_address,mem_size;
int loop, i;
int *ptr, *mem_address_current;
printf("mem_addr: %s\n",argv[1]);
printf("mem_size: %s\n",argv[2]);
mem_address = strtol(argv[1], NULL, 16);
mem_size = strtol(argv[2], NULL, 16);
printf("mem_addr: %x\n",mem_address);
printf("mem_size: %x\n",mem_size);
int mem_dev = open("/dev/mem", O_RDWR);
if(mem_dev == -1)
{
printf("No worky\n");
exit(1);
}
int alloc_mem_size, page_mask, page_size;
void *mem_pointer, *virt_addr;
page_size = sysconf(_SC_PAGESIZE);
alloc_mem_size = (((mem_size / page_size) + 1) * page_size);
page_mask = (page_size - 1);
mem_pointer = mmap(NULL,
alloc_mem_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
mem_dev,
(mem_address & ~page_mask)
);
if(mem_pointer == MAP_FAILED)
{
printf("no_worky2\n");
exit(1) ;
}
virt_addr = (mem_pointer + (mem_address & page_mask));
ptr = mem_pointer;
loop = (mem_size/16) + 1;
for(i = 0;i < loop;i++) {
printf("%#x: %08x %08x %08x %08x\n", ptr, *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3));
ptr = ptr + 4;
}
return 0;
}
如果运行以下命令,将获得期望的值。
root@p1025:~# ./test_prog_ppc 0100000 16
mem_addr: 0100000
mem_size: 16
mem_addr: 100000
mem_size: 16
0x48001000: 38210020 4e800020 9421ffe0 7c0802a6
0x48001010: 2c050000 bf410008 7c7e1b78 90010024
然而,如果我更改输入地址,该值会与预期值不同:
root@p1025:~# ./test_prog_ppc ffee0000 16
mem_addr: ffee0000
mem_size: 16
mem_addr: 7fffffff
mem_size: 16
有什么想法是为什么会发生这种情况吗?
感谢帮助。
strtol()
函数的名称暗示它返回一个(带符号的)long
整数,但是你却将其存储在一个无符号整型变量中。这只会导致溢出。你可能需要使用strtoul()
函数,并将结果存储在一个无符号长整型变量中。你还应该传递一个非空的第二个参数,以便能够检查错误。 - Crowmanprintf("%p: ...\n", ptr, ...)
或printf("%#lx: ...\n", (unsigned long) ptr, ...)
。 - chux - Reinstate Monica