不正确编译引发内存错误
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.
解决所有依赖关系
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.
解决所有依赖关系
相关文章推荐
- vs2012 函数参数内存对齐引发编译错误
- 代码修改正确后,为什么编译连接还是有错误?!
- 宏不正确的写法,导致编译错误
- 解决android混淆编译出现Proguard returned with error code 1和文件名、目录名或卷标语法不正确错误
- JAVA的正确配置(配置验证正确,但编译后无法执行的错误所在!)
- 正确理解PHP程序编译时的错误信息
- 项目引用不当,可能引发编译错误
- Qt5 : 使用QtDesigner的时候查看代码正确 但是编译的时候总出现 为定义的错误
- cpp文件编译正确 c文件编译一堆错误
- 由编译错误看-L. -lxxxx的正确位置
- VS2010中程序编译生成都是正确的,直接生成的exe也是正确的,就是在VS中运行出现错误
- 正确理解PHP程序编译时的错误信息
- 字符集引发的编译错误
- 字符集引发的编译错误
- 编译大量JAVA文件内存错误解决办法
- exe中用new一块内存,但是在dll程序中delete引发的错误
- 看起来正确的代码也会隐藏着格式错误导致编译错误
- Memcached出现:请确保在编译时已将xxx.StringMessages”正确嵌入或链接到程序集“xxx” 的错误
- linux下编译复数类型引发的错误:expected unqualified-id before '(' token
- 在const成员函数中使用下标[]操作map成员引发编译错误