手动测试和修改多线程中栈空间大小。

2024-03-01 13:48

本文主要是介绍手动测试和修改多线程中栈空间大小。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

每个线程都有一个堆栈那么,这个堆栈多大呢?

HANDLE CreateThread(
       LPSECURITY_ATTRIBUTES lpThreadAttributes,
       SIZE_T dwStackSize,
       LPTHREAD_START_ROUTINE lpStartAddress,
       LPVOID lpParameter,
       DWORD dwCreationFlags,
       LPDWORD lpThreadId
);

在创建线程的时候可以指定堆栈大 小,dwStackSize=0则使用默认大小


-那默认大小又是多少?

      写个小程序算一下~

#include <stdio.h>
#include <windows.h>

#define STACK_SIZE 0.5*1024*1024

DWORD WINAPI ThreadFunc(PVOID pvParam)
{
      DWORD dwRet = 0;
      printf("%-3d:0x%x\n",pvParam,&dwRet); 
      return dwRet;
}

int
main(int,char**)
{
      DWORD dwTid;
      printf("Main:0x%x\n",&dwTid); 
      for(int i=0;i<50;i++)
        CreateThread(NULL,STACK_SIZE,ThreadFunc,(PVOID)i,0,&dwTid); // 莫小注:原作者这处代码有错,这不能修改线程栈大小

      Sleep(2000);
    return 0; 
}

输出:

Main:0x12ff78
0       :0x50ffb0
1       :0x60ffb0
2       :0x70ffb0
3       :0x80ffb0
4       :0x90ffb0

0x60ffb0 - 0x50ffb0 = 0x100000 byte = 1MB

那么这个小程序中线程最小堆栈大小为1MB. (对么?为什么呢?后面有验证)
将STACK_SIZE换成0, 结果和上面一样
将STACK_SIZE换成2, 结果变成2MB

以下是从MSDN中查到的

Generally, the reserve size is the default reserve size specified in the executable header. However, if the initially committed size specified by dwStackSize is larger than the default reserve size, the reserve size is this new commit size rounded up to the nearest multiple of 1 MB.

根据winnt.h中的      IMAGE_OPTIONAL_HEADER结构体
typedef struct _IMAGE_OPTIONAL_HEADER {
       //
        // Standard fields.
        //

        WORD        Magic;
        BYTE        MajorLinkerVersion;
        BYTE        MinorLinkerVersion;
        DWORD       SizeOfCode;
        DWORD       SizeOfInitializedData;
        DWORD       SizeOfUninitializedData;
        DWORD       AddressOfEntryPoint;
        DWORD       BaseOfCode;
        DWORD       BaseOfData;

        //
        // NT additional fields.
        //

        DWORD       ImageBase;
        DWORD       SectionAlignment;
        DWORD       FileAlignment;
        WORD        MajorOperatingSystemVersion;
        WORD        MinorOperatingSystemVersion;
        WORD        MajorImageVersion;
        WORD        MinorImageVersion;
        WORD        MajorSubsystemVersion;
        WORD        MinorSubsystemVersion;
        DWORD       Win32VersionValue;
        DWORD       SizeOfImage;
        DWORD       SizeOfHeaders;
        DWORD       CheckSum;
        WORD        Subsystem;
        WORD        DllCharacteristics;
        DWORD       SizeOfStackReserve;
        DWORD       SizeOfStackCommit;
        DWORD       SizeOfHeapReserve;
        DWORD       SizeOfHeapCommit;
        DWORD       LoaderFlags;
        DWORD       NumberOfRvaAndSizes;
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

我推测,应该可以在链接期间指定栈大小
查看link.exe的参数

/STACK:reserve[,commit]
果然如此~~

看到网上有人问如何改变默认的线程堆栈大小,在MSDN中有答案:

The default size for the reserved and initially committed stack memory is specified in the executable file header. Thread or fiber creation fails if there is not enough memory to reserve or commit the number of bytes requested. To specify a different default stack size for all threads and fibers, use the STACKSIZE statement in the module definition (.def) file. For more information on these default sizes and how to change them, see the documentation included with your linker.

(模块定义 (.def) 文件为链接器提供有关被链接程序的导出、属性及其他方面的信息)

可见,默认线程堆栈大小在链接阶段可以由程序员指定

 

 

以上部分载自他人空间.

MSDN中有段话很重要:

To change the reserved stack size, set the dwCreationFlags parameter of CreateThread or CreateRemoteThread toSTACK_SIZE_PARAM_IS_A_RESERVATION and use the dwStackSize parameter. 

我用MSDN2001版查看的时候,它有注明STACK_SIZE_PARAM_IS_A_RESERVATION 适用于XP系统, 在MSDN2008版没注明了,我是在XP下测试的

下面是我改的测试代码:

代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 #include "stdafx.h"
#include <stdio.h>
#include <windows.h>#define STACK_SIZE 64*1024 // 设置线程栈为64KDWORD WINAPI ThreadFunc(PVOID pvParam)
{DWORD dwRet = 0;printf("%-3d:0x%x\n",pvParam,&dwRet);Sleep(2000);  // 避免线程退出,这个线程栈地址又被分配给其它新创建的线程return dwRet;
}int main(int,char**)
{DWORD dwTid;printf("Main:0x%x\n",&dwTid);HANDLE handles[10];for(int i=0;i<10;i++){handles[i] = CreateThread(NULL,STACK_SIZE,ThreadFunc,(PVOID)i,STACK_SIZE_PARAM_IS_A_RESERVATION ,&dwTid);Sleep(100); // 保证每次Create后得到的线程栈地址是递增的}for(int i=0; i<10; i++){CloseHandle(handles[i]);}getchar();return 0;
}

-----CreateThread(NULL,STACK_SIZE,ThreadFunc,(PVOID)i,STACK_SIZE_PARAM_IS_A_RESERVATION ,&dwTid);

运行结果:


每次相差(10000)x = (655366)d = 64*1024, 设置成功,64K.

另外, Linux平台的栈默认大小应该是8192KB, Windows平台的栈默认大小应该是1024KB, 项目移植的时候要注意设置, 免得空间不足, 分配失败




这篇关于手动测试和修改多线程中栈空间大小。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/762649

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

SQL Server 查询数据库及数据文件大小的方法

《SQLServer查询数据库及数据文件大小的方法》文章介绍了查询数据库大小的SQL方法及存储过程实现,涵盖当前数据库、所有数据库的总大小及文件明细,本文结合实例代码给大家介绍的非常详细,感兴趣的... 目录1. 直接使用SQL1.1 查询当前数据库大小1.2 查询所有数据库的大小1.3 查询每个数据库的详

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

Qt中实现多线程导出数据功能的四种方式小结

《Qt中实现多线程导出数据功能的四种方式小结》在以往的项目开发中,在很多地方用到了多线程,本文将记录下在Qt开发中用到的多线程技术实现方法,以导出指定范围的数字到txt文件为例,展示多线程不同的实现方... 目录前言导出文件的示例工具类QThreadQObject的moveToThread方法实现多线程QC

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

2025版mysql8.0.41 winx64 手动安装详细教程

《2025版mysql8.0.41winx64手动安装详细教程》本文指导Windows系统下MySQL安装配置,包含解压、设置环境变量、my.ini配置、初始化密码获取、服务安装与手动启动等步骤,... 目录一、下载安装包二、配置环境变量三、安装配置四、启动 mysql 服务,修改密码一、下载安装包安装地

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab