您的位置:首页 > 其它

不正确编译引发内存错误

2014-07-17 11:32 260 查看
--------------------------------------------------------------------------------

author: hjjdebug

date: Thu Jul 17 11:20:59 CST 2014

--------------------------------------------------------------------------------

这里演示的编译错误

不是普通的无类型,无函数原型, 格式不正确错误。这些错误可以由编译器指出。

而是编译,连接已经通过,由于编译不完整造成的错误。

运行时出现:

Cannot access memory at address , 内存错误

引起内存错误的原因有多种,这是其中的一种。 而且,往往会令你目瞪口呆,百思不得其解。

这里就来详细揭示其过程。

演示:

一个代码。 file1 文件为A 类, file2 文件为B 类, B 类使用了A 类变量,

A 类头文件更改,而使用它的file2 未编译会是什么结果。

--------------------------------------------------------------------------------

准备简单的测试代码 file1.cpp(file1.h), file2.cpp(file2.h)

--------------------------------------------------------------------------------

[hjj@hjj ~/test]$ cat file1.h file1.cpp

#ifndef _FILE_1

#define _FILE_1

typedef struct _A

{

int a;

// 第一次不加aa 变量生成执行文件。结果正常。

// 第二次加aa 变量,但只编译file1, 演示不正确的连接会是什么结果

// int aa;

int b;

int c;

}A;

#endif

#include <stdio.h>

#include "file1.h"

#include "file2.h"

int main(int argc, char *argv[])

{

A x;

x.a = 1;

x.b = 2;

x.c = 3;

B y;

y.printv(&x);

return 0;

}

[hjj@hjj ~/test]$ cat file2.h file2.cpp

#ifndef _FILE_2

#define _FILE_2

#include "file1.h"

class B

{

public:

void set(A *o){m_o=o;}

void printv(A *x);

private:

A* m_o;

};

#endif

#include <stdio.h>

#include "file2.h"

void B::printv(A *x)

{

printf("a: %d\n",x->a);

printf("b: %d\n",x->b);

printf("c: %d\n",x->c);

}

--------------------------------------------------------------------------------

Makefile:

file2.o 也依赖于file1.h, 但这里故意没有写,造成编译不完整

一些不完善的Makefile, 有可能存在这些瑕疵。

--------------------------------------------------------------------------------

[hjj@hjj ~/test]$ cat Makefile

all: test

test: file1.o file2.o

g++ -o test file1.o file2.o

file1.o : file1.cpp file1.h

g++ -c -g -o $@ $<

file2.o : file2.cpp file2.h

g++ -c -g -o $@ $<

clean:

rm *~ *.o test

[hjj@hjj ~/test]$

--------------------------------------------------------------------------------

gdb 调试: 真相大白。

--------------------------------------------------------------------------------

[hjj@hjj ~/test]$ gdb test

GNU gdb (GDB) 7.6

(gdb) b main

Breakpoint 1 at 0x4005b3: file file1.cpp, line 7.

(gdb) r

Starting program: /home/hjj/test/test

Breakpoint 1, main (argc=1, argv=0x7fffffffe2b8) at file1.cpp:7

7 x.a = 1;

(gdb) n

8 x.b = 2;

(gdb)

9 x.c = 3;

(gdb)

11 y.printv(&x);

(gdb) p x

$1 = {a = 1, aa = 32767, b = 2, c = 3}

(gdb) ptype x

type = struct _A {

int a;

int aa;

int b;

int c;

}

(gdb) p &x

$2 = (A *) 0x7fffffffe1c0

--------------------------------------------------------------------------------

这之前我们看到的a,b,c 都已正确赋值

--------------------------------------------------------------------------------

(gdb) s

B::printv (this=0x7fffffffe1b0, x=0x7fffffffe1c0) at file2.cpp:5

5 printf("a: %d\n",x->a);

(gdb) p x

$3 = (A *) 0x7fffffffe1c0

(gdb) p *x

$4 = {a = 1, b = 32767, c = 2}

(gdb) ptype x

type = struct _A {

int a;

int b;

int c;

} *

--------------------------------------------------------------------------------

调用函数之后, b 值,c 值忽然不对=了。你是否非常惊讶,

谁改变了b值,c值??

打印它的类型,发现file2 的B 类型与 file1中的B 类型不一致!

编译出的.o 文件, 是按照偏移来访问成员变量的,而不是按照所谓的名称。

这些结构信息保存在.o调试信息中,gdb 可以识别出来。

这里的b值,c值,是结构基地址加偏移。 这里的b,c值是按照旧结构,而调用者按照新结构。

数据运算必然会造成混乱。 尤其是当结构中包含指针。 后面拿不到正确指针,造成非法访问内存。

所以说,没有人改变b值,c值,是对不上口造成的。

--------------------------------------------------------------------------------

(gdb)

解决办法: make clean, make all.

解决所有依赖关系
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: