问题描述:
调用自编译库函数时,函数内部分配内存,函数返回后会得到结构体首地址,程序现象是结构体内数据意想不到地被改变了,主要考虑方向为越界访问,后调试发现竟然是结构体内元素地址发生了变化,当然最终也是导致越界访问;
问题解决
结构体大小在编译时期是确定好的,内部元素地址不可能动态变化,结构体寻找内部元素是按照头文件定义指定的,所以是编译库函数与应用程序时的头文件不同导致的,这是在更新库函数include时,应用程序还是使用的旧版本头文件编译的,所以导致最后,库函数中地址与返回后应用程序中地址不同。
验证
先写一个 a.c
#include "a.h"
#include <stdlib.h>
#include <string.h>
struct ST *func(void)
{
struct ST *val = malloc(10);
printf("A 0x%x a 0x%x, b 0x%x\n", val, &val->a, &val->b);
return val;
}
a.h 中定义的结构体是两个 char 类型
#ifndef __A__
#define __A__
struct ST
{
char a;
char b;
};
#endif
将a.c 文件编译成.o 文件,然后链接到main.c中,生成可执行程序;
main.c: 方便起见,直接在文件中重定义结构体ST, 元素为两个 int 类型
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
struct ST
{
int a;
int b;
};
extern struct ST *func();
int main()
{
struct ST *p = func();
printf("p 0x%x a 0x%x b 0x%x\n", p, &p->a, &p->b);
free(p);
p = NULL;
return 0;
}
最后结果为
可以看到,b 的地址在func函数内外发生了变化。
最后
问题很简单,因为确信是越界访问导致数据改变,所以一直在寻找可能越界的地方,毕竟调用的其他函数库,代码不熟悉,而且代码量庞大,再加上交叉编译工具GDB调试不太好使,寻找问题的过程却很繁琐,在这个过程中才发现结构体元素地址发生了变化。
问题很新奇,特此记录。