zoukankan      html  css  js  c++  java
  • 线程的堆栈

    每当创建一个线程的时候,系统会为线程的堆栈保留一个栈区的空间区域,并将一些物理存储器提交给这个已保留的区域,我查看了VS2015,该默认设置大小是1MB。

    它可以自己设置,在 项目-->属性-->链接器-->系统--->堆栈保留大小 这个地方填写自己希望的栈大小。

    // 堆保留大小 1M    堆提交大小 4KB
    // 栈保留大小 1M    栈提交大小 4KB

    在页面大小是4KB的计算机上创建一个堆栈区域,其物理存储均具有页面保护属性,即PAGE_READWRITE。

    线程访问时,从栈顶到栈底,页面状态不断变为已提交的页面,但是最底下的页面总是被保留的,从来不会被提交,这样做的目的是为了防止不小心改写进程所需要的其他数据。因为如果栈底下方的地址上,另一个地址空间区域已经提交了物理存储器,那么就有可能改写了其他数据,这是非常危险又隐蔽的错误。
    结合SEH异常处理机制,可以写一个简单的求和函数,用递归的方法,让它发生栈溢出,并对异常进行捕获。

    #include "stdafx.h"
    #include <windows.h>

    // 堆保留大小 1M 堆提交大小 4KB
    // 栈保留大小 1M 栈提交大小 4KB

    UINT Sum(UINT uNum);
    LONG WINAPI FilterFunc(DWORD dwExceptionCode);
    DWORD WINAPI SumThreadFunc(PVOID Param);


    int main()
    {

    DWORD ThreadId;

    UINT uSum = 5000; //大概可以计算4700以内的数

    HANDLE ThreadHandle = CreateThread(NULL, 0,
    SumThreadFunc, (PVOID)(UINT_PTR)uSum, 0, &ThreadId);


    WaitForSingleObject(ThreadHandle, INFINITE);

    GetExitCodeThread(ThreadHandle, (PDWORD)&uSum);
    CloseHandle(ThreadHandle);

    if (uSum == UINT_MAX)
    {


    printf("The number is too big, please enter a smaller number ");
    }
    else
    {
    printf("%d ", uSum);
    }
    return 0;
    }

    UINT Sum(UINT uNum)
    {


    return((uNum == 0) ? 0 : (uNum + Sum(uNum - 1)));
    }

    LONG WINAPI FilterFunc(DWORD dwExceptionCode)
    {

    return((dwExceptionCode == STATUS_STACK_OVERFLOW)
    ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH);
    }


    DWORD WINAPI SumThreadFunc(PVOID Param)
    {
    UINT uSumNum = PtrToUlong(Param);  //指针转ULONG
    UINT uSum = UINT_MAX; // 错误数字

    __try
    {

    uSum = Sum(uSumNum);  //递归求和
    }
    __except (FilterFunc(GetExceptionCode())) //如果是EXCEPTION_EXECUTE_HANDLER  (1)
    {
    // 说明堆栈溢出
    // 添加一些自己的处理
    printf("堆栈溢出了 ");
    }


    return uSum;
    }

    创建独立线程的理由:
    1.每个线程保证拥有自己的1MB堆栈空间,而不是和他人分享1MB

    2.当发生溢出时,每个线程只得到一次通知

    3.系统自动收回提交给堆栈的物理存储器。

  • 相关阅读:
    JS 图像上传前实现压缩
    php解决微信开发中用户昵称中的特殊字符与emoji表情写入mysql错误的问题
    PHP 删除非法UTF-8字符
    解决airserver在Windows下安装失败的问题
    微信开发自定义菜单数组结构
    在MAC下配置MySQL 5.7 数据库的编码问题
    MAC 系统升级10.10以后PHP验证码错误的解决办法。[ 一行代码轻松解决! ]
    解决ubuntu server mysql load data infile 导入本地文件ERROR 1148 (42000)错误。
    MySQL 批量导入 csv 文件
    bobo【转】使用jQuery解析JSON数据
  • 原文地址:https://www.cnblogs.com/kekoukele987/p/7428471.html
Copyright © 2011-2022 走看看