欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

指针返回无法访问问题

程序员文章站 2022-06-04 19:35:51
...

返回指针无法访问的问题主要是进行了非法地址的访问,这里主要说一种不常见的错误,在32位程序移植到64位系统时候出现的返回值无法访问的问题。

问题现象:出现 data abort的错误

实质是程序访问了非法地址,嵌入式中出现data abort一般考虑是内存mmu配置中的地址映射出现问题,但是如果是程序移植需要考虑编译器的一个特性。请看下面的代码

1、test.c文件

#include <stdio.h>
#include <stdlib.h>

void main()
{
	int * a = NULL;
	long long tmp = 0x1234567887654321;
	printf("%s:%d 0x%llx\n", __func__, __LINE__, tmp);
	a = (int *)return_p();
	printf("%s:%d a[0x%p]\n", __func__, __LINE__, a);
	

}

2、tmp.c文件

void *return_p()
{
	return (void *)0xfedcba00;
}

3、编译命令:

$ gcc test.c tmp.c 
test.c: In function ‘main’:
test.c:11:13: warning: implicit declaration of function ‘return_p’ [-Wimplicit-function-declaration]
  a = (int *)return_p();
             ^
test.c:11:6: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  a = (int *)return_p();

4、生成a.out文件

5、运行结果

$ ./a.out 
main:10 0x1234567887654321
main:12 a[0x0xfffffffffedcba00]

这个结果并不是正确的结果正确的结果应该为:

$ ./a.out 
main:10 0x1234567887654321
main:12 a[0x0xfedcba00]

错误就处在:编译时候出现的警告,正是这个警告出现出现了当前的问题。

test.c:11:6: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  a = (int *)return_p();

这个错误的出现的过程为:

1、不能明确return_p()的返回值

2、return_p()返回64位的地址

3、return_p()返回的64位地址赋给整形(32位)

4、32位整型再转为64位的指针。

其中就是第3步和第4步,是导致问题的关键:

1、第3步,截断了高32位的数据,导致地址最终可能出现异常

2、第4步,32位付给64位时[31]如果为1,则认为此变量为负数,则将64位的高32位全部置1,低32位复制,导致地址出现错误。

解决问题的方法,便是让编译器知道return_p()的返回值,最简单有效的方法是在代码调用函数接口前声明。

将test.c文件修改如下,变可获取正常地址

#include <stdio.h>
#include <stdlib.h>

extern void *return_p();

void main()
{
	int * a = NULL;
	long long tmp = 0x1234567887654321;
	printf("%s:%d 0x%llx\n", __func__, __LINE__, tmp);
	a = (int *)return_p();
	printf("%s:%d a[0x%p]\n", __func__, __LINE__, a);
	

}