来自strtol的意外输出

Ger*_*rdo 3 c embedded embedded-linux

我正在尝试创建一个小程序,它接收物理内存位置并打印存储在该位置的数据.我将两个参数传递给程序 - 我要打印的内存的地址和大小(以字节为单位).

我遇到的问题是当我传入的地址超过某个值时,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;


}
Run Code Online (Sandbox Code Playgroud)

如果我运行以下命令,我会得到预期的值.

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
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改输入地址,则值会从预期变化:

root@p1025:~# ./test_prog_ppc ffee0000 16
mem_addr: ffee0000
mem_size: 16
mem_addr: 7fffffff
mem_size: 16
Run Code Online (Sandbox Code Playgroud)

有关为什么会发生这种情况的任何想法?

谢谢您的帮助.

Cro*_*man 5

strtol()返回(签名)long.根据您的输入,您尝试解析无符号的32位数,因此如果long您的系统是32位,则将strtol()超出范围.在这种情况下,它将返回LONG_MAX,在您的系统上显示为0x7FFFFFFF.

您应该使用strtoul()相反的方法,并将结果存储在一个unsigned long,而不是unsigned int像现在一样,因为虽然long保证至少为32位,但int不是.

另外,你真的应该将真实指针的地址作为第二个参数strtol()和朋友一起传递,并使用它来检查错误.现在,如果其中一个argv[1]或者argv[2]没有以数字开头,您将无法区分输入是否错误,或输入是否为合法零.