但编译器不做检查
‘壹’ 为什么编译器不检查数组越界
效率问题!数组用的太多了,每次都检测越界情况,会消耗很大的系统开销!
与编译器无关,只与内存管理机制有关,是操作系统级别的问题,堆栈的读取方式只是数据结构上的不同,在机器层面,依然是单纯的内存读写操作;
数组越界访问的危险性不好评估,但确实是最严重的危险之一;
结果基本上会100%崩溃,但是崩溃的原因很可能不一样,就算是同一段越界代码跑几遍,原因也可能是不一样的;
指针越界问题是不限于数组访问的,所以全面点的解释如下:
C语言的编译时,会跟你的代码需要,首先申请一块栈空间和堆空间,栈的优先级较高,一般时存放程序运行所必须的数据和变量,内存上是连续的,堆空间是程序运行时动态申请的空间,内存上一般是不连续的,这里说的栈与你自己创建的栈不是一个栈,不过数据结构是一样的,只不过你自己创建的栈是靠你自己写的代码动态创建的,所以其实是在你程序的堆空间中的;
下面关键问题来了,
以上所有内存空间就是你的程序在跑起来之后,向操作系统申请的所有空间,换句话说,这些内存以外的数据,都是不属于你这个程序的资源,当你使用指针操作的时候,如果你的指针越界了,那么接下来你对这个指针的操作就是非法的了,如果这段空间依然是你程序内部的资源,通常会导致你程序自己崩溃,如果是程序之外的资源一般就更糟糕了,甚至会导致更高级别的崩溃,原因很多:
比如你篡改了不属于你的数据,导致该数据所属对象的逻辑混乱;
比如越界区域存在保护,内存空间是有读写权限控制的,如果接下来你对只读的空间进行写操作,也会导致崩溃,windows下你会看到非常亲切的蓝屏;
等等...
这也是内存溢出攻击的基本思想;
‘叁’ sonarqube 分析C++ 代码时,为什么无法检测出问题
有些错误是编译器无法检查的
编译器只能检查你语法是不是错误但无法检查你算法是否错误
看来可能你中间有哪步有严重错误了,以至于系统要强制关闭程序,好好检查一下吧
‘肆’ C语言的编译器为什么不检查数组下标越界
以前还真没想过,记得老师讲的时候也没说,就是强调这是C语言的历史问题,从一开始就没有,后来这个功能也没有加上。至于具体的原因已知模棱两可,今天总算查清楚了。 综合网上的各种资料,可以得到如下的结果: 1. 在一个固定的机器之下,指针所占的位数都是一样的,换言之,保存的地址是有最大值的,这样如果每次都检查数组的越界问题,会对指针的功能做出很大的限制,因为指针只是包含地址信息并没有包含长度的信息,比如一个 char ch[100]; char * test=ch; 之后test也可以只想超过100的长度的字符串类型,并不是局限与100。如果检测长度,那么就相当与限制的指针的长度,这是不合理的。 2. 没有效率,需要付出代价。具体:最早的C编译器并不检查下标,而最新的编译器依然不对它进行检查。这项任务之所以很困难,是因为下标引用可以作为任意的指针,而不仅仅是数组名。作用于指针的下标引用的有效性既依赖于该指针当时恰好指向什么内容,也依赖于下标的值。结果,C的下标检查所涉及的开销比你开始想象的要多。编译器必须在程序中插入指令,证实下标的结果所引用的元素和指针表达式所指向的元素属于同一个数组。这个比较操作需要程序中所有数组的位置和长度方面的信息,这将占用一些空间。当程序运行时,这些信息必须进行更新,以反映自动和动态分配的数组,这又将占用一定的时间。因此,即使是那些提供了下标检查的编译器通常也会提供一些开关,允许你去掉下标检查。
‘伍’ 在java中已检查异常和位未检查异常是什么二者有何区别
1、含义不同:检查异常就是编译器要求你必须处置的异常。不知道你编程的时候有没有遇到过,你写的某段代码,编译器要求你必须要对这段代码trycatch,或者throwsexception。
非检查异常是编译器不要求强制处置的异常,虽然有可能出现错误,但是不会在编译的时候检查。
2、运行时情况不同:运行时异常都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是非检查异常,程序中可以选择捕获处理,也可以不处理。
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。
如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不要自定义检查异常。
3、解决方式不同:检查异常继续抛出,消极的方法,一直可以抛到java虚拟机来处理,就是通过throwsexception抛出。用try...catch捕获。注意,对于检查的异常必须处理,或者必须捕获或者必须抛出。
对未检查的异常捕获;继续抛出;不处理。
一般是不处理的,因为你很难判断会出什么问题,而且有些异常你也无法运行时处理,比如空指针,需要人手动的去查找,而且,捕捉异常并处理的代价远远大于直接抛出。
(5)但编译器不做检查扩展阅读:
所有异常类型都是Throwable类的子类,它包含Exception类和Error类,Exception又包括checkedexception和uncheckedexception。
uncheckedexception:Java编译器不要求对未检查异常一定捕获或抛出,可以不做处理。此类异常通常是在逻辑上有错误,可以通过修改代码避免。在eclipse中(保存即编译)编译后此类异常发生处会报错。
checkedexception:Java编译器要求对检查异常必须捕获或抛出,代码逻辑没有错误,但程序运行时会因为IO等错误导致异常,你在编写程序阶段是预料不到的。
如果不处理这些异常,程序将来肯定会出错。所以编译器会提示你要去捕获并处理这种可能发生的异常,不处理就不能通过编译。
‘陆’ 关于C语言,为什么编译器不对数组的越界进行检查
为了提高代码效率。
C语言跟Java不同,C的内存管理交由用户处理,Java是语言自己处理。但是,如果不是核心系统开发,一般体现不出两者的内存处理的代码之间效率差别。
‘柒’ (c语言)我找到问题了,编译器没有报错,还可以运行,谁能解答一下
你这代码错了
能运行但是,不建议这样写,因为有歧义
%s->字符串(char[])占位符
%c->单个字符(char)占位符
char a;//单个字符
char s[10];//字符串
scanf("%c",&a);//输入单个字符
scanf("%s",s);//输入字符串
printf("%c",a);//输出单个字符
printf("%s",s);//输出字符串
‘捌’ keil编译器运行为什么检测不到错误
答:这种情况是你的程序还有别的错误,
当你把别的错误改掉后,再编译你的vid 就会提示错误。
这种情况keil 经常有的。
‘玖’ 为什么scala 编译时异常可以不用捕获
不用捕获是因为Scala 编译器不做这方面检查啊,自然你不捕获不抛出也能过编译。至于为什么Scala 编译器不检查异常,是因为语言设计者们认为异常不是好的错误处理实践。理由如下:
1,异常会打断执行流,因此不是类型安全的
2,异常不利于类型推断
3,从实践来看,大部分程序员并不会认真处理异常,不是catch下打个log就是继续往外throw了事,结果就是又臭又长的throw
4, 丑,这是原罪。
Scala 鼓励使用类型来表示错误信息,例如Option与Future ,Either, 选择与未来(:-D),这样控制流里你可以带着错误信息一直往下走,直到一个能优雅处理错误的位置。
‘拾’ if(-1 == argc) 是什么情况
-1 == argc 这是一个关系表达式,判断argc是否与 -1 相等
那为什么不写成 argc == -1呢
因为,如果,按照 argc==-1,效果一样,但如果不小心写成 argc = -1 变成一个赋值,显然
会出现语义上的错误,但编译器是不检查语义错误的。这样,显然得不到想要的结果。
但 你这样写 -1 == argc,如果,你不小心写成 -1 = argc,这是语法错误,编译器会帮你检查到出现了错误。以此利用编译器来帮你避免错误。