关于内存越界和覆盖的面试题.

WalkerJack 2010-11-08 09:08:04
今天在网上看了一个C/C++面试题,
实在不知怎么解答,所以来请教大家,
代码如下:


1 #include <stdio.h>
2 int main()
3 {
4 char x,y,z;
5 int i;
6 int a[16];

7 for(i=0;i<=16;i++)
8 {
9 a[i]=0;
10 printf("\n");
11}
12 return 0;
13 }


博主说当时面试官要求第行以下的代码不能更改,能让程序正确运行。
看看大家有什么好办法不?
...全文
378 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
moonflow 2011-08-29
  • 打赏
  • 举报
回复
看下栈上分布不是知道了。
zwhfly 2011-06-20
  • 打赏
  • 举报
回复
定义一个类c,重载++、int()、=、<=等运算符,改int i为c i,应该行吧。
maoxing63570 2010-11-10
  • 打赏
  • 举报
回复
当用户定义了一个数组,而此数组刚好在其所在页的下边界,且此页的下一页刚好是自由或者预留的(不是提交的,即没有真正的物理存储)。当程序不小心向下越界访问此数组,则首先引发缺页错误。随即虚拟内存管理器在处理缺页错误时检测到它也不在调页文件中,这就是所谓的"访问违例"(access violation)。访问违例意味着要访问的地址所在的虚拟内存页还没有被提交,即没有实际的物理存储与之对应,访问违例会直接导致整个进程退出(即crash)。

可以看到,指针越界访问的后果根据运行时实际情况而有所不同。如上所述,当数组并非处于其所在页的边界,越界后还在同一页中,这时只会"误访问"(误读或误写,其中误读只会影响到正在执行的代码;误写则会影响到其他处代码的执行)该页中其他数据,而不会导致整个进程的crash。即使在该数组真的处于其所在页的边界,且越界后指针值落在了其相邻页。但如果此相邻页碰巧也为一个提交页,此时仍然只是"误访问",也不会导致进程的crash。这也意味着,同一个应用程序的代码中存在着指针越界访问错误,运行时有时crash,但有时则不会。

所以我们来研究这些问题。This doesn't make any sense.
zhutianjin4355255 2010-11-10
  • 打赏
  • 举报
回复
[Quote=引用楼主 walkerjack 的回复:]
今天在网上看了一个C/C++面试题,
实在不知怎么解答,所以来请教大家,
代码如下:


C/C++ code

1 #include <stdio.h>
2 int main()
3 {
4 char x,y,z;
5 int i;
6 int a[16];

7 for(i=0;i<=16;i++)
8 {
9 a[i]=0;
10 printf("\n");……
[/Quote]


很简单; for(i=0;i<=16;i++)
改成 for(i=0;i<16;i++)
xuwening 2010-11-10
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 nossiac 的回复:]

引用 12 楼 zfmy_lhb 的回复:

int a[17];就可以了。。。

我第一反应也就这.我以为楼主是来搞笑的.

如果考官想考数组越界的话,这个程序是很不严谨的.
变量在内存中的排列,取决于编译器的实现,以及优化与否.

楼上几位兄弟的分析过于想当然了.
[/Quote]

确实不严谨~~~~~
这个例子明显是用数组越界挖个坑,给大家跳~~~~~~~~然后一副自以为是的丑恶嘴脸就出来了,你告诉如何如何……不说了,再说就吐了~~~
xiaozhi5855 2010-11-10
  • 打赏
  • 举报
回复
lz的分析取决于编译器的类型,如果是小端模式,你这种说法是真确的,如果是大端模式,这种说法说不过去。
wjb_yd 2010-11-10
  • 打赏
  • 举报
回复
额,看了13楼的回复,发现我之前分析的偏了,一直没注意i 就是循环变量。
13楼说的基本是对的,前提是编译器没做手脚,让i和数组分配在连续的内存地址上。
不过话又说回来了,既然这样,干脆把数组改成17就结了~
redleaves 2010-11-09
  • 打赏
  • 举报
回复
乱七八糟自以为是的题...
这种依赖于undefined/unspecified行为的题本就不应该出现在世界上...
楼主只要搞清楚,数组访问越界是undefined行为.而栈中数据的排列是unspecified行为.代码中不要出于undefined行为.且不要写依赖于某些unspecified行为的代码就好.
东大坡居士 2010-11-09
  • 打赏
  • 举报
回复
一般栈都是从高地址到低地址分配。。
堆才是从低地址到高地址分配。。
东大坡居士 2010-11-09
  • 打赏
  • 举报
回复
是啊,不能确定变量的分配顺序啊
nossiac 2010-11-09
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 zfmy_lhb 的回复:]

int a[17];就可以了。。。
[/Quote]
我第一反应也就这.我以为楼主是来搞笑的.

如果考官想考数组越界的话,这个程序是很不严谨的.
变量在内存中的排列,取决于编译器的实现,以及优化与否.

楼上几位兄弟的分析过于想当然了.
yiruirui0507 2010-11-09
  • 打赏
  • 举报
回复
#include <stdio.h>
int main()
{
char x,y,z;
int i;
//int temp;
int a[16];

for(i=0;i<=16;i++)
{
a[i]=0;
printf("\n");
}

return 0;
}

如果把那句话给注释掉了,在VC下会出现死循环,原因如下:
根据变量定义的顺序可以知道i的地址刚好位于数组的下一个地址,也就是a[16]的地址,因此当循环到
for(i=0;i<=16;i++)
{
a[i]=0;
printf("\n");
}
当i=16的时候,a[i]=a[16]=0,这个时候变量i=0,所以i<16,循环会继续,一直到死!
所以解决办法在变量 i跟数组a之间增加一块空间,达到分离这两个地址的目的.
可以如下解决:
int temp;
或者
char w;
都OK,
分析完毕!
yiruirui0507 2010-11-09
  • 打赏
  • 举报
回复
看了看楼上的答案,多少有点让我失望.说以下我的答案吧!希望给各位一点提示:
那我就荣幸了!

#include <stdio.h>
int main()
{
char x,y,z;
int i;
int temp;
int a[16];

for(i=0;i<=16;i++)
{
a[i]=0;
printf("\n");
}

return 0;
}

请注意我的实现细节!
zfmy_lhb 2010-11-09
  • 打赏
  • 举报
回复
int a[17];就可以了。。。
wjb_yd 2010-11-09
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wjb_yd 的回复:]
自己为是的出题者,一行代码都不用改,你用release版本的编译就可以了。
是VS编译器的__RTC_CheckEsp搞的鬼,debug模式下,vs会在每个对数组的操作之后插入这个函数以检验是否有数组越界,到了release模式下,这些都没了,自然也就不会出错了,不过那样的话变量i的值也意外的变成了0。
[/Quote]
纠正一下,上面写错了,刚才又看了一下反汇编,不是_RTC_CheckEsp,是_RTC_CheckStackVars,不好意思。_RTC_CheckEsp是检查栈帧的函数~

而且这个函数不是“在每个对数组的操作之后插入”,而是在函数返回时一次性检查的。
希望没有误导lz~
tracyjk 2010-11-09
  • 打赏
  • 举报
回复
围观~~~~
wjb_yd 2010-11-09
  • 打赏
  • 举报
回复
自己为是的出题者,一行代码都不用改,你用release版本的编译就可以了。
是VS编译器的__RTC_CheckEsp搞的鬼,debug模式下,vs会在每个对数组的操作之后插入这个函数以检验是否有数组越界,到了release模式下,这些都没了,自然也就不会出错了,不过那样的话变量i的值也意外的变成了0。
Csuxiaowu 2010-11-08
  • 打赏
  • 举报
回复
楼主面的哪家?
平安?融通?BBK?
sb345146049 2010-11-08
  • 打赏
  • 举报
回复
我什么都看不懂,晕死
bo_00 2010-11-08
  • 打赏
  • 举报
回复
难道是强调 a[16]=0;越界了???那就int a[17];呗
加载更多回复(5)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧