线程的堆栈——Windows核心编程学习手札之十六
線程的堆棧
——Windows核心編程學(xué)習(xí)手札之十六
系統(tǒng)會(huì)在進(jìn)程的地址空間內(nèi)保存一些區(qū)域,同時(shí)也會(huì)在進(jìn)程地址空間內(nèi)為線程的堆棧保留區(qū)域。線程都有自己的堆棧,創(chuàng)建時(shí),系統(tǒng)就保留一個(gè)堆棧空間區(qū)域,并將相應(yīng)物理存儲(chǔ)器提交給這個(gè)保留的區(qū)域用于線程堆棧。按照默認(rèn)設(shè)置,系統(tǒng)保留1MB的地址空間并提交兩個(gè)頁(yè)面的內(nèi)存,默認(rèn)值可以在鏈接應(yīng)用程序時(shí)設(shè)定Microsoft的鏈接程序的/STACK選項(xiàng):
/STACK:reserve[,commit]
當(dāng)創(chuàng)建一個(gè)線程的堆棧時(shí),系統(tǒng)就會(huì)保留一個(gè)鏈接程序/STACK開關(guān)指明的地址空間區(qū)域。在調(diào)用CreateThread或_beginthreadx函數(shù)時(shí),可以重載原先提交的內(nèi)存數(shù)量,這兩個(gè)函數(shù)都有一個(gè)參數(shù),可以用來(lái)重載原先提交給堆棧地址空間的內(nèi)存數(shù)量,如果設(shè)定這個(gè)參數(shù)為0,那么系統(tǒng)將使用/STACK開關(guān)指明的已提交的堆棧大小值。
線程堆棧溢棧例子,超過(guò)1MB分配空間,SHE提示出錯(cuò):
// Demo.cpp : Defines the entry point for the application.
//
?
#include "stdafx.h"
#include "resource.h"
#include? <process.h>??
?
#define MAX_LOADSTRING 100
#define UINT_MAX? 4
// Global Variables:
HINSTANCE hInst;??????????????????????????????????????????????????????? // current instance
TCHAR szTitle[MAX_LOADSTRING];??????????????????????????????????????????????????????? // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];????????????????????????????????????????????????? // The title bar text
?
// Foward declarations of functions included in this code module:
ATOM????????????????????????? MyRegisterClass(HINSTANCE hInstance);
BOOL????????????????????????? InitInstance(HINSTANCE, int);
LRESULT CALLBACK? WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK? About(HWND, UINT, WPARAM, LPARAM);
?
//Function:Sum
//An example of calling Sum for uNum=0 through 9
//uNum:0 1 2 3 4?? 5? 6? 7? 8? 9 ...
//Sum: 0 1 3 6 10 15 21 28 36 45 ...
UINT Sum(UINT nNum)
{
?????? // call Sum recursively.
?????? return ( (nNum ==0)?0:(nNum+Sum(nNum-1)) );
}
//end of Sum
?
//Function:FilterFunc
LONG WINAPI FilterFunc(DWORD dwExceptionCode)
{
?????? return ((dwExceptionCode==STATUS_STACK_OVERFLOW)?
???????????? EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH);
}
//end of FilterFunc
?
//Function:SumThreadFunc
//the separate thread that is responsible for calculating the sum.
unsigned int? WINAPI SumThreadFunc(PVOID pvParam)
{
?????? //the parameter pvParam,contains the number of integers to sum.
?????? UINT uSumNum=PtrToUlong(pvParam);
??? //uSum contains the summation of the numbers from 0 through uSumNum.
?????? //if the sum cannot be calculated,a sum of UINT_MAX is returned.
??? UINT uSum=UINT_MAX;
?????? __try{
????????????? uSum=Sum(uSumNum);
?????? }
?????? __except(FilterFunc(GetExceptionCode())){
?????? }
?????? return(uSum);
}
//end of SumThreadFunc
int APIENTRY WinMain(HINSTANCE hInstance,
???????????????????? HINSTANCE hPrevInstance,
???????????????????? LPSTR???? lpCmdLine,
???????????????????? int?????? nCmdShow)
{
????? // TODO: Place code here.
?????? MSG msg;
?????? HACCEL hAccelTable;
?
?????? // Initialize global strings
?????? LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
?????? LoadString(hInstance, IDC_DEMO, szWindowClass, MAX_LOADSTRING);
?????? MyRegisterClass(hInstance);
?
?????? // Perform application initialization:
?????? if (!InitInstance (hInstance, nCmdShow))
?????? {
????????????? return FALSE;
?????? }
?
?????? hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_DEMO);
?
?????? // Main message loop:
?????? while (GetMessage(&msg, NULL, 0, 0))
?????? {
????????????? if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
????????????? {
???????????????????? TranslateMessage(&msg);
???????????????????? DispatchMessage(&msg);
????????????? }
?????? }
?
?????? return msg.wParam;
}
?
?
?
//
//? FUNCTION: MyRegisterClass()
//
//? PURPOSE: Registers the window class.
//
//? COMMENTS:
//
//??? This function and its usage is only necessary if you want this code
//??? to be compatible with Win32 systems prior to the 'RegisterClassEx'
//??? function that was added to Windows 95. It is important to call this function
//??? so that the application will get 'well formed' small icons associated
//??? with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
?????? WNDCLASSEX wcex;
?
?????? wcex.cbSize = sizeof(WNDCLASSEX);
?
?????? wcex.style??????????????????? = CS_HREDRAW | CS_VREDRAW;
?????? wcex.lpfnWndProc?????? = (WNDPROC)WndProc;
?????? wcex.cbClsExtra?????????? = 0;
?????? wcex.cbWndExtra???????? = 0;
?????? wcex.hInstance???????????? = hInstance;
?????? wcex.hIcon????????????????? = LoadIcon(hInstance, (LPCTSTR)IDI_DEMO);
?????? wcex.hCursor??????? = LoadCursor(NULL, IDC_ARROW);
?????? wcex.hbrBackground???? = (HBRUSH)(COLOR_WINDOW+1);
?????? wcex.lpszMenuName???? = (LPCSTR)IDC_DEMO;
?????? wcex.lpszClassName???? = szWindowClass;
?????? wcex.hIconSm???????????? = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
?
?????? return RegisterClassEx(&wcex);
}
?
//
//?? FUNCTION: InitInstance(HANDLE, int)
//
//?? PURPOSE: Saves instance handle and creates main window
//
//?? COMMENTS:
//
//??????? In this function, we save the instance handle in a global variable and
//??????? create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
?? HWND hWnd;
?
?? hInst = hInstance; // Store instance handle in our global variable
?
?? hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
????? CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
?
?? if (!hWnd)
?? {
????? return FALSE;
?? }
?
?? ShowWindow(hWnd, nCmdShow);
?? UpdateWindow(hWnd);
?
?? return TRUE;
}
?
//
//? FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//? PURPOSE:? Processes messages for the main window.
//
//? WM_COMMAND??? - process the application menu
//? WM_PAINT???? - Paint the main window
//? WM_DESTROY????? - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
?????? int wmId, wmEvent;
?????? PAINTSTRUCT ps;
?????? HDC hdc;
?????? TCHAR szHello[MAX_LOADSTRING];
?????? LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
?
?????? switch (message)
?????? {
????????????? case WM_COMMAND:
???????????????????? wmId??? = LOWORD(wParam);
???????????????????? wmEvent = HIWORD(wParam);
???????????????????? // Parse the menu selections:
???????????????????? switch (wmId)
???????????????????? {
?????? ????????????? ??? case IDM_CALC:
??????????????????? {
?????????????????????????????????? UINT uSum=44000;
?????????????????????????????????? unsigned dwThreadId;
?????????????????????????????????? HANDLE hThread=(HANDLE)_beginthreadex(NULL,0,SumThreadFunc,(PVOID)(UINT_PTR)uSum,0,&dwThreadId);
?????????????????????????????????? //wait for the thread to terminate.
?????????????????????????????????? WaitForSingleObject(hThread,INFINITE);
?????????????????????????????????? //the thread's exit code is the resulting summation.
?????????????????????????????????? GetExitCodeThread(hThread,(PDWORD)&uSum);
?????????????????????????????????? CloseHandle(hThread);
?????????????????????????????????? if(uSum==UINT_MAX)
????????????????????????????????????????? MessageBox(hWnd,"error","warning",0);
?????????????????????????????????? else
??????????????????????? MessageBox(hWnd,"Success","warning",0);
?????????????????????????????????? }
??????????????????? break;
??????????????????????????? case IDM_ABOUT:
??????????????????????????? ?? DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
??????????????????????????? ?? break;
??????????????????????????? case IDM_EXIT:
??????????????????????????? ?? DestroyWindow(hWnd);
??????????????????????????? ?? break;
??????????????????????????? default:
??????????????????????????? ?? return DefWindowProc(hWnd, message, wParam, lParam);
???????????????????? }
???????????????????? break;
????????????? case WM_PAINT:
???????????????????? hdc = BeginPaint(hWnd, &ps);
???????????????????? // TODO: Add any drawing code here...
???????????????????? RECT rt;
???????????????????? GetClientRect(hWnd, &rt);
???????????????????? DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
???????????????????? EndPaint(hWnd, &ps);
???????????????????? break;
????????????? case WM_DESTROY:
???????????????????? PostQuitMessage(0);
???????????????????? break;
????????????? default:
???????????????????? return DefWindowProc(hWnd, message, wParam, lParam);
?? }
?? return 0;
}
?
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
?????? switch (message)
?????? {
????????????? case WM_INITDIALOG:
??????????????????????????? return TRUE;
?
????????????? case WM_COMMAND:
???????????????????? if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
???????????????????? {
??????????????????????????? EndDialog(hDlg, LOWORD(wParam));
??????????????????????????? return TRUE;
???????????????????? }
???????????????????? break;
?????? }
??? return FALSE;
}
?
總結(jié)
以上是生活随笔為你收集整理的线程的堆栈——Windows核心编程学习手札之十六的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 在应用程序中使用虚拟内存——Window
- 下一篇: 工作整理