求指导!存在函数中的字符串 为什么能读回主函数?
求指点!存在函数中的字符串 为什么能读回主函数??
以下程序感觉很奇怪,定义在函数中的字符串数组, 通过指针数组的传参,居然能保留在主函数中。
不是说,函数结束 释放内存吗? 那在主函数中通过地址打印出来的 字符串 难道没有被清除??
为什么会这样?
越看越糊涂,希望高人指点。
#include <stdio.h>
#include <stdlib.h>
void Input(char *pname[]);
int main()
{
int i,n;
char *name[10];
Input(name);
for(i=0;i<2;i++)
{
printf("%s,%p\n",name[i],name[i]);
}
return 0;
}
void Input(char *pname[])
{
int i, j, k, n = 0;
char ch[50][100];
printf("%p",ch);
for (i = 0; i<2; i++)
{
scanf("%s", ch[i]);
pname[i] = ch[i];
}
}
运行结果如下:

------解决方案--------------------
对于栈内存,严格来说,不象堆内存那样有分配和释放这两个概念。
------解决方案--------------------
堆内存分配和释放算法要维护一个带标记头信息的内存占用块和可用内存块的链表,对分配和释放的顺序无特殊要求。具体可参考Linux源代码中malloc和free的代码。
而所谓栈内存“分配”和“释放”就很简单了,仅仅对应加减堆栈指针寄存器esp的值而已(针对X86架构),必须按照和“分配”相反的顺序“释放”。
------解决方案--------------------
补充一下,栈地址向下增长是地址变得越来越小,刚才描述时候为了说明问题,用了变越来越大的方式来说明了。
------解决方案--------------------
这和是否一维数组无关,只和栈分配有关。
你说的破坏未破坏的标准是依赖于printf的输出吗?如果是这样的话,那是有风险的,因为printf本身就是函数调用,很有可能破坏栈数据的。
要验证是否被破坏掉,要在for语句前设置断点,然后用VC的memory窗口看原始数据才行。
------解决方案--------------------
释放内存只是更改了内存占用的标记,实际内存中的数据可能不会马上销毁
以下程序感觉很奇怪,定义在函数中的字符串数组, 通过指针数组的传参,居然能保留在主函数中。
不是说,函数结束 释放内存吗? 那在主函数中通过地址打印出来的 字符串 难道没有被清除??
为什么会这样?
越看越糊涂,希望高人指点。
#include <stdio.h>
#include <stdlib.h>
void Input(char *pname[]);
int main()
{
int i,n;
char *name[10];
Input(name);
for(i=0;i<2;i++)
{
printf("%s,%p\n",name[i],name[i]);
}
return 0;
}
void Input(char *pname[])
{
int i, j, k, n = 0;
char ch[50][100];
printf("%p",ch);
for (i = 0; i<2; i++)
{
scanf("%s", ch[i]);
pname[i] = ch[i];
}
}
运行结果如下:
------解决方案--------------------
对于栈内存,严格来说,不象堆内存那样有分配和释放这两个概念。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Input(char *pname[]);
void Input2(char *pname[])
{
int i, j, k, n = 0;
char ch[50][100];
printf("%p",ch);
for (i = 0; i<2; i++)
{
memset((void *)ch[i],'A',99);ch[99]=0;
pname[i] = ch[i];
}
}
int main()
{
int i,n;
char *name[10];
Input(name);
Input2(name);
for(i=0;i<2;i++)
{
printf("%s,%p\n",name[i],name[i]);
}
return 0;
}
void Input(char *pname[])
{
int i, j, k, n = 0;
char ch[50][100];
printf("%p",ch);
for (i = 0; i<2; i++)
{
scanf("%s", ch[i]);
pname[i] = ch[i];
}
}
------解决方案--------------------
堆内存分配和释放算法要维护一个带标记头信息的内存占用块和可用内存块的链表,对分配和释放的顺序无特殊要求。具体可参考Linux源代码中malloc和free的代码。
而所谓栈内存“分配”和“释放”就很简单了,仅仅对应加减堆栈指针寄存器esp的值而已(针对X86架构),必须按照和“分配”相反的顺序“释放”。
------解决方案--------------------
补充一下,栈地址向下增长是地址变得越来越小,刚才描述时候为了说明问题,用了变越来越大的方式来说明了。
------解决方案--------------------
这和是否一维数组无关,只和栈分配有关。
你说的破坏未破坏的标准是依赖于printf的输出吗?如果是这样的话,那是有风险的,因为printf本身就是函数调用,很有可能破坏栈数据的。
要验证是否被破坏掉,要在for语句前设置断点,然后用VC的memory窗口看原始数据才行。
------解决方案--------------------
释放内存只是更改了内存占用的标记,实际内存中的数据可能不会马上销毁