user-0 提问: 关于memset初始化内容超过限制问题

回复:
user: user-1
content: 其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

user: user-2
content: 你的b只分配了四个字节，而memset是按照字节来算，memset(b,0,8)你这里要设置8个字节的内存，就溢出了；

user: user-3
content: 越界破坏了栈，提示就那个意思  另外编译器怎么排列 a b c 三个变量是不确定的，未必一定是a b c 顺序排列，你可以看对应的汇编代码

user: user-4
content: 越界行为，memset对于非b的区域初始化，其实和赋值是一样的，对于越界很容易导致段错误，数据不正确等结果； 我们的内存有管理机制，是系统的处理的

user: user-5
content: 村子里各家种自家的地，法律上不允许越界，如果都守规矩就能有预定的收获，如果越界了，就可能得不到自己想要的东西

user: user-6
content: a b c 的内存顺序未必是 abc 或者 cba 编译器按照自己的逻辑 怎么排列好用就怎么排 越界之后 修改的未必是 a c 你检查a c 的值毫无意义

user: user-7
content: calloc free 管理的内存，术语称作堆 用个不恰当的比方来形容堆的话 你可以把他想象为飞机或者火车的座位！callo 和 free就是售票程序 并不是calloc创造了指针，free不是销毁了指针。 而是类似于售票程序只是给你一张票。并且在系统中标记那个座位有人定了 如果中途有人改签之类的情况，free只是把那个座位重新标记为可以再给别人 所以，你用calloc订购一个座位，如果这个航班乘员比较少。那么你也可以做到别的座位上。

user: user-8
content: 用gcc试的可以通过，而且没有那段提示。 用vc debug试的遇到断言退出 用vc release试的没错误提示  可能就是某些gcc版本发现b越界赋值给你一句警告。

user: user-1
content: 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

user: user-9
content: 函数内的局部变量是放在stack里的，因为栈是向下增长的，在进入一个函数之前，会先把参数和下一步要执行的指令地址（通过call实现）压栈，在函数的入口会把ebp压栈，并把esp赋值给ebp，在函数返回的时候，将ebp值赋给esp，pop先前栈内的上级函数栈的基地址给ebp，恢复原栈基址，然后把调用函数之前的压入栈的指令地址pop出来（通过ret实现）。 栈是由高往低增长的，而数组的存储是由低位往高位存的，如果越界的话，会把当前函数的ebp和下一跳的指令地址覆盖掉，如果覆盖了当前函数的ebp，那么在恢复的时候esp就不能指向正确的地方，从而导致未可知的情况，如果下一跳的地址也被覆盖掉，那么肯定会导致crash。

user: user-10
content: 引用 5 楼 jianwufeng26 的回复:[quote=引用 3 楼 qq_36409192 的回复:] [quote=引用 2 楼 jianwufeng26 的回复:] [quote=引用 1 楼 qq_36409192 的回复:] memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误[/quote] http://blog.csdn.net/xyzso1z/article/details/70333085?locationNum=1&fps=1[/quote] 看了，还是没明白，  memset(b,0,8)应该是把b之后的4字节也初始化为0了；a,b,c正常输出了，但为什么会出现stack smashing detected   这个错误呢？  [/quote] 正常输出并不等于没有错误。就像scanf输入一样，并不会检查是否溢出了。

user: user-0
content: 引用 3 楼 qq_36409192 的回复:[quote=引用 2 楼 jianwufeng26 的回复:] [quote=引用 1 楼 qq_36409192 的回复:] memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误[/quote] http://blog.csdn.net/xyzso1z/article/details/70333085?locationNum=1&fps=1[/quote] 看了，还是没明白，  memset(b,0,8)应该是把b之后的4字节也初始化为0了；a,b,c正常输出了，但为什么会出现stack smashing detected   这个错误呢？

user: user-11
content: memset(b,0,8);  是将数组b的内容全部赋值为0，又因为数组b只开辟了四个字节的空间，而你却把从b[o]开始以后的8个字节全部赋值为0，后面的四个字节的空间不属于你的，则会栈溢出操作

user: user-10
content: 引用 2 楼 jianwufeng26 的回复:[quote=引用 1 楼 qq_36409192 的回复:] memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误[/quote] http://blog.csdn.net/xyzso1z/article/details/70333085?locationNum=1&fps=1

user: user-0
content: 引用 1 楼 qq_36409192 的回复:memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误

user: user-10
content: memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。