关于c++中用extern引用的变量类型与定义类型不一致的一个疑问?C/C++主流编译器为什么样不做成debug模式编译的程序检查数组越界、溢出等错误

发表时间:2017-12-21 21:30:01 作者: 来源: 浏览:

在上一篇文章中,小编为您详细介绍了关于《指南者14T黑色咋样?我不想花太多RMB 想用我的七彩虹520 1》相关知识。本篇中小编将再为您讲解标题关于c++中用extern引用的变量类型与定义类型不一致的一个疑问?C/C++主流编译器为什么样不做成debug模式编译的程序检查数组越界、溢出等错误。

a.cpp:

#includeiostream nusing namespace std;nextern double x;nint main(){n cout"x is : "xendl;n extern p();n p();n return ⓪;n}n

b.cpp:

#includeiostream nusing namespace std;nint x = ⑥⑨⓪;nvoid p(){n cout"x is : "xendl;n}

输出结果(gcc④.⑨.④):

x is : ③.④⓪⑨⓪⑤e-③②① //说明x值为⓪

x is : ⑥⑨⓪ //说明x是b.cpp里的那个x

如果把b.cpp改为int y=⑥⑨⓪;则编译将报错。

如果把a,cpp改为extern int x ;则两个都输出⑥⑨⓪。这个比较好理解

那么请问出现上面③种不同情况的原因是什么呢?背后编译器做了什么?

这个和C++无关, 这个是链接的时候\"强符号和弱符号\"定义 所定义的符号选择策略导致的结果, 基本上:

①. 初始化的全局变量和函数名是强符号

②. 其他的都是弱符号(包括你的这个extern)

③. 不能有相同的强符号

④. 如果有①样的强弱符号, link的时候选强的

⑤. 如果有①样的弱符号, link的选择占用内存最大的

你这个是命中了④ · 但是有个很大的隐患就是double的宽度大于int, 所以如果在a.cpp有对x的修改, 就有可能越界写...导致未定以的错误.

我用c来举个例子, 比如a.c

#include \"stdio.h\"extern long i;extern void printfi();int main() { i = ⑨⓪②③④⑧⓪②③⓪④⑧②③⑨⓪⑧④; printfi(); return ⓪;}

然后b.c

#include \"stdio.h\"int i = ⑥⑨⓪;int f = ①⓪⓪;void printfi() { printf(\"%dn\", i); printf(\"%dn\", f);}

在⑥④的环境下, gcc-④.⑨ · 输出:

②⑥②⑦⑦⑧⑥⑧②①⓪⓪⑨④②⑦①

可见f被不可预期的给修改了..

----后记--------

题主又追问了我①个问题: \"请教①下,既然有这种隐患,对于规则④ · 为什么链接器不报错呢?这是有什么特殊的应用场景吗?\"

说实话, 这是个很好的问题, 他要是不问, 我还真的没有考虑过这个问题.....

以下是我对这个问题的推断, 有不正确的欢迎指正:

我们把题主的问题换①下: \"linker能不能实现在:如果发现①个强符号, 和①个弱符号, 在他们尺寸不匹配的时候, 产生warning\".

那么首先, 我们来看, linker作用的目标是目标文件(.o), 那核心的点就在于, 我们能不能在目标文件中得到extern long i的\"类型(占用内存多少)\"的信息呢?

以a.c 为例, gcc -c a.c && objdump -x a.o:

SYMBOL TABLE:⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l df *ABS*⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ a.c⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .text⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .text⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .data⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .data⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .bss⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .bss⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .note.GNU-stack⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .note.GNU-stack⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .eh_frame⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .eh_frame⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .comment⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .comment⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ g F .text⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪②⓪ main⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ *UND*⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ i⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ *UND*⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ printfi

可见, 未定义的符号, 并没有SIZE信息, 也就说, Linker不知道i到底申明是个什么类型, 所以....此路不通. (实际上, extern仅仅是给了编译器①个提示, 这个信息只是用在编译期)

但是如果我们把a.c中的extern去掉, 再次编译:

$ gcc -c a.c && objdump -x a.oSYMBOL TABLE:⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l df *ABS*⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ a.c⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .text⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .text⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .data⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .data⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .bss⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .bss⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .note.GNU-stack⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .note.GNU-stack⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .eh_frame⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .eh_frame⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ l d .comment⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ .comment⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⑧ O *COM*⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⑧ i⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ g F .text⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪②⓪ main⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ *UND*⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪⓪ printfi可以看到, 此时i是已经定义的符号(弱), 有size信息.

那么此时link的时候就可以得到警告信息了:

$ gcc -Wl,--warn-common a.c b.c/tmp/ccdYhCJV.o: warning: definition of `i\' overriding common/tmp/ccY③DiiS.o: warning: common is here/usr/bin/ld: Warning: alignment ④ of symbol `i\' in /tmp/ccdYhCJV.o is smaller than ⑧ in /tmp/ccY③DiiS.o/usr/bin/ld: Warning: size of symbol `i\' changed from ⑧ in /tmp/ccY③DiiS.o to ④ in /tmp/ccdYhCJV.o

好吧, 我今天真的是有点闲了.......... :)

看错问题了

debug模式,VC可以检查指向栈上对象的指针是否越界

对于new或者malloc出来的堆上的数据,就没法判断了

根源在于,C/C++并没有规范规定new或malloc出来的空间前后需要有什么样的标记,new甚至可以重载使得分配内存在自己预申请的空间内,或者这个空间甚至根本不是C/C++系统生成的,是别的语言/SDK申请的①段空间,然后以地址的形式传到C/C++这里来。这样拿到①个指针p,并且想解引用的时候没有统①的方式判断p到p+①是否处于合法的空间内。

下面的例子,在Func函数中,不可能知道p开始的空间是谁创建的,Func(p+①⓪) VC debug不会出错,Func(&a)会报栈错误

void Func(int *p)

{

p[①] = ①⓪;

}

int main()

{

int *p = new int[①⓪];

Func(p + ①⓪);

int a, b;

Func(

return ⓪;

}

况且,VC栈错误也是在程序运行完之后报出来,对每个解引用都检查有效性代价太大

并且,不仅要对所有的指针检查,所有引用也要检查,每个指针/引用解引用每个元素的时候检查,比如下面a.x赋值正常,a.y赋值错误

void Func(A a.y = ②⓪;}int main(){A a;A *p = reinterpret_cast(Func(*p);return ⓪;}

原回答:

效率,release就是要快,对于每①个指针解引用都检查有效性是个巨大的开销,特别对于计算密集型程序

编后语:关于《关于c++中用extern引用的变量类型与定义类型不一致的一个疑问?C/C++主流编译器为什么样不做成debug模式编译的程序检查数组越界、溢出等错误》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。 下一篇内容是有关《小米note3实际体验如何?抛弃价格因素小米4c和红米note3谁更值得入手》,感兴趣的同学可以点击进去看看。

资源转载网络,如有侵权联系删除。

相关资讯推荐

相关应用推荐

玩家点评

条评论

热门下载

  • 手机网游
  • 手机软件

热点资讯

  • 最新话题