一道笔试题。。求答案
给一个函数:
void fun(void)
{
}
int main()
{
int x = 1;
int y = 2;
fun();
printf("x,y%d %d\n",x,y);
}
问,如何实现函数fun,使得最后的打印结果不是1 2
[解决办法]
// 这个算不算?!
#include <stdlib.h>
#include <stdio.h>
void fun(void)
{
int x = 10, y = 20;
printf("x,y%d %d\n",x,y);
exit(0);
}
int main()
{
int x = 1;
int y = 2;
fun();
printf("x,y%d %d\n",x,y);
}
[解决办法]
我觉得这道题是想改内存吧,
在vs的Release模式下,你在fun中申请另外2个局部变量,
这个局部变量的地址和x,y的地址是连续的,这样就可以改内存了.
但是在vs的debug模式和Linux下都不是连续的...
[解决办法]
这种题目需要对Window的栈比较了解. 我对Windows的栈不太懂, 但是要实现该目标肯定要修改栈, 也就是手动做栈溢出. 以下代码在VS2008 debug下可以实现, 因为Release下会根据代码做各种优化, 我没找出压栈的规律(因为func太短,还涉及到内联).
#include <iostream>
using namespace std;
void func()
{
int a[1] = {0};
*(int*)((char*)&a[0] + 0xec) = 100;
*(int*)((char*)&a[0] + 0xe0) = 200;
}
int main()
{
int x = 1;
int y = 2;
func();
cout << "x = " << x << endl;
cout << "y = " << y << endl;
system("pause");
return 0;
}
其实就像楼上说的, 这种题目意义不大, 最多就是考察下是否了解函数压栈.
[解决办法]
利用数组越界来修改相邻内存区域内所保存的值,
考的就是栈的知识。
[解决办法]
#include <stdio.h>遍历下就可以吧
#pragma pack(push)
int fun(void)
{
int a=0;
int *p;
p=&a;
while(*p!=1)
{
p++;
}
*p=10;
}
int main()
{
int x=1;
int y=2;
fun();
printf("%d %d\n",x,y);
}
#pragma pack(pop)
[解决办法]
开阔思路的题吧,除了前面说到的结束进程、堆栈溢出方法外,我再给一个:
int fun(void)
{
#define printf
}
[解决办法]
因为编译程序会把 变量,程序代码 分开放在不同的节区
当然也有先后的排列顺序
所以从排在"前面的"变量的地址指针开始往后找...
[解决办法]
准确点说void fun(void)
{
int a=0;
int *p=&a;
while(1)
{
if((*p==1)&&(*(p-1)==2)) break;
p++;
}
*p=88; //x的地址
*(p-1)=99; //y的地址
}
怎么可以确定p++一定能取到x的地址?局部变量有没有可能按照地址从小到大的顺序存储?
你分配的变量都是要压栈的,说白了就是一块内存,定义变量的时候就保存一个数据,连续的
如果*p==1并且*(p-1)==2,几本可以确定p就对准了x,p-1就对准了y
因为x,y先分配,处于栈的靠底一端,而a后分配,处于靠栈顶一端
所以用a的地址来找x的地址,要用++
确定了p对准x,p-1对准y后
直接通过对*p和*(p-1)赋值,就可以改变x,y的值,所以,输出自然就变了