I have written a small program to check the page alignment. This program works fine when I hardcode the value of address variable in program itself, but when I try to take them from commandline using argc and argv values, the output goes haphazard, does the value of uint64_t cannot be recovered from commandline using atoi function..?
我写了一个小程序来检查页面对齐。当我在程序本身硬编码地址变量的值时,这个程序运行正常,但是当我尝试使用argc和argv值从命令行获取它们时,输出变得偶然,uint64_t的值是否无法使用atoi函数从命令行恢复。 。?
normal code, one can see the value of address being hardcoded into program itself.
普通代码,可以看到地址的值被硬编码到程序本身。
1 #include<stdio.h>
2 #include<stdlib.h>
3
4 int aligned(uint64_t addr, uint64_t pgsize){
5 return ((uint64_t)addr % pgsize == 0);
6 }
7
8 int main(int argc, char*argv[]){
9 uint32_t i;
10 uint64_t addr, size;
11 addr=0x1900000000;
12 size=0x100000000 ;
13
14 for(i=0;i<7;i++)
15 if(aligned(addr,size>>i)){
16 printf("Aligned to %#lx\n",size>>i);
17 }
18 else
19 printf("Not Aligned to %#lx\n",size>>i);
20 return 0;
21 }
output
产量
[souravhimanshu] ./aligned
Aligned to 0
Aligned to 0x80000000
Aligned to 0x40000000
Aligned to 0x20000000
Aligned to 0x10000000
Aligned to 0x8000000
Aligned to 0x4000000
code with command line input
代码与命令行输入
1 #include<stdio.h>
2 #include<stdlib.h>
3
4 int aligned(uint64_t addr, uint64_t pgsize){
5 return ((uint64_t)addr % pgsize == 0);
6 }
7
8 int main(int argc, char*argv[]){
9 uint32_t i;
10 uint64_t addr, size;
11 if(argc<2){
12 printf("usage ./chkalign <address>\n");
13 exit(-1);
14 }
15 addr=atoi(argv[1]);
16 printf("%#lx",addr);
17 //addr=0x1900000000;
18 size=0x100000000 ;
19
20 for(i=0;i<7;i++)
21 if(aligned(addr,size>>i)){
22 printf("Aligned to %#lx\n",size>>i);
23 }
24 else
25 printf("Not Aligned to %#lx\n",size>>i);
26 return 0;
27 }
output (incorrect)
输出(不正确)
[sourav@himanshu] ./chkalign 0x924000000
0Aligned to 0
Aligned to 0x80000000
Aligned to 0x40000000
Aligned to 0x20000000
Aligned to 0x10000000
Aligned to 0x8000000
Aligned to 0x4000000
as we can see the value of addr when printed after atoi function shows 0.
因为我们可以看到在atoi函数显示0后打印时addr的值。
kindly advise...
好心提醒...
2 个解决方案
#1
1
You did not specify a platform, be aware that memory addresses are not necessarily the same size as int
. atoi
returns an int
, hence the problem.
您没有指定平台,请注意内存地址的大小不一定与int相同。 atoi返回一个int,因此问题。
Even long
may not be large enough to hold a memory address (as in Windows IIRC). Therefore you should use strtoull
returning an unsigned long long
guaranteed to be at least 64 bits. Also use 0
as the base for conversion, allowing addresses to be entered as 0x80000000
on the command line. Also be more consistent and portable with your types: long
is not necessarily 64 bits, so it should not be printed as "%lx"
in printf
.
即使很长也可能不足以容纳内存地址(如在Windows IIRC中)。因此,您应该使用strtoull返回无符号长long,保证至少为64位。也使用0作为转换的基础,允许在命令行上输入地址为0x80000000。您的类型也更加一致和便携:long不一定是64位,所以它不应该在printf中打印为“%lx”。
Also work on your style. Consistency helps avoid bugs.
也适用于你的风格。一致性有助于避免错误。
Here is a corrected version:
这是一个更正版本:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int aligned(uint64_t addr, uint64_t pgsize) {
return (addr % pgsize) == 0;
}
int main(int argc, char *argv[]) {
int i;
uint64_t addr, size;
if (argc < 2) {
printf("usage: ./chkalign <address>\n");
exit(-1);
}
addr = strtoull(argv[1], NULL, 0);
printf("Address %#llx:\n", (unsigned long long)addr);
//addr = 0x1900000000;
size = 0x100000000;
for (i = 0; i < 7; i++) {
if (aligned(addr, size >> i)) {
printf("Aligned to %#llx\n", (unsigned long long)size >> i);
} else {
printf("Not Aligned to %#llx\n", (unsigned long long)size >> i);
break;
}
}
return 0;
}
#2
1
The number 0x924000000
is in hex so you should use strtol()
and store it in long
数字0x924000000是十六进制的,因此您应该使用strtol()并将其存储为long
addr=strtol(argv[1], NULL, 16);
#1
1
You did not specify a platform, be aware that memory addresses are not necessarily the same size as int
. atoi
returns an int
, hence the problem.
您没有指定平台,请注意内存地址的大小不一定与int相同。 atoi返回一个int,因此问题。
Even long
may not be large enough to hold a memory address (as in Windows IIRC). Therefore you should use strtoull
returning an unsigned long long
guaranteed to be at least 64 bits. Also use 0
as the base for conversion, allowing addresses to be entered as 0x80000000
on the command line. Also be more consistent and portable with your types: long
is not necessarily 64 bits, so it should not be printed as "%lx"
in printf
.
即使很长也可能不足以容纳内存地址(如在Windows IIRC中)。因此,您应该使用strtoull返回无符号长long,保证至少为64位。也使用0作为转换的基础,允许在命令行上输入地址为0x80000000。您的类型也更加一致和便携:long不一定是64位,所以它不应该在printf中打印为“%lx”。
Also work on your style. Consistency helps avoid bugs.
也适用于你的风格。一致性有助于避免错误。
Here is a corrected version:
这是一个更正版本:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int aligned(uint64_t addr, uint64_t pgsize) {
return (addr % pgsize) == 0;
}
int main(int argc, char *argv[]) {
int i;
uint64_t addr, size;
if (argc < 2) {
printf("usage: ./chkalign <address>\n");
exit(-1);
}
addr = strtoull(argv[1], NULL, 0);
printf("Address %#llx:\n", (unsigned long long)addr);
//addr = 0x1900000000;
size = 0x100000000;
for (i = 0; i < 7; i++) {
if (aligned(addr, size >> i)) {
printf("Aligned to %#llx\n", (unsigned long long)size >> i);
} else {
printf("Not Aligned to %#llx\n", (unsigned long long)size >> i);
break;
}
}
return 0;
}
#2
1
The number 0x924000000
is in hex so you should use strtol()
and store it in long
数字0x924000000是十六进制的,因此您应该使用strtol()并将其存储为long
addr=strtol(argv[1], NULL, 16);