wordpress   发布时间:2022-04-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了CreateThread()在64位Windows上失败,在32位Windows上运行.为什么?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

操作系统: Windows XP 64位,SP2. 我有一个不寻常的问题.我正在将一些代码从32位移植到64位. 32位代码工作得很好.但是当我为64位版本调用CreateThread()时,调用失败.我有三个失败的地方. 2调用CreateThread(). 1调用beginthreadex()调用CreateThread(). 所有三个调用都失败,错误代码为0x3E6,“对内存位置的访问无效”
操作系统: Windows XP 64位,SP2.

我有一个不寻常的问题.我正在将一些代码从32位移植到64位. 32位代码工作得很好.但是当我为64位版本调用CreateThread()时,调用失败.我有三个失败的地方. 2调用CreateThread(). 1调用beginthreadex()调用CreateThread().

所有三个调用都失败,错误代码为0x3E6,“对内存位置的访问无效”.

问题是所有输入参数都是正确的.

HANDLE  h;
DWORD   threadID;

h = CreateThread(0,// default security
                 0,// default stack size
                 myThreadFunc,// valid function to call
                 myParam,// my param
                 0,// no flags,start thread immediately
                 &threadID);

对CreateThread()的所有三次调用都是从我在程序执行开始时注入目标程序的DLL(这是在程序到达main()/ WinMain()之前)开始的.如果我通过说菜单从目标程序(相同的参数)调用CreateThread(),它就可以工作.相同的参数等奇怪.

如果我传递NULL而不是& threadID,它仍然会失败.

如果我将NULL作为myParam传递,它仍然会失败.

我不是从DllMain()内部调用CreateThread,所以这不是问题.我很困惑,在谷歌等搜索没有显示任何相关的答案.

如果有人以前见过这个或有任何想法,请告诉我.

谢谢阅读.

回答

简短回答:x64上的堆栈帧需要16字节对齐.

更长的回答:
在对调试器墙猛烈抨击并发布对各种建议的响应之后(所有这些都有所帮助,促使我尝试新方向)我开始在调用CreateThread()之前探索堆栈上的内容.事实证明这是一个红鲱鱼,但它确实导致了解决方案.

向堆栈添加额外数据会更改堆栈帧对齐.迟早,其中一个测试会使您进行16字节堆栈帧对齐.那时代码工作了.所以我回溯了我的步骤并开始将NULL数据放入堆栈而不是我认为正确的值(我一直在推送返回地址来伪造一个调用帧).它仍然有效 – 所以数据并不重要,它必须是实际的堆栈地址.

我很快意识到堆栈的16字节对齐.以前我只知道数据的8字节对齐.这microsoft document explains all the alignment requirements.

如果堆栈帧在x64上没有16字节对齐,则编译器可能会在将数据推入堆栈时将大(8字节或更多)数据放在错误的对齐边界上.

因此我面临的问题 – 使用未在16字节边界上对齐的堆栈调用挂钩代码.

对齐要求的快速摘要,表示为大小:对齐

> 1:1
> 2:2
> 4:4
> 8:8
> 10:16
> 16:16

大于8字节的任何内容在2边界的下一个幂上对齐.

我认为微软的错误代码有点误导.最初的STATUS_DATATYPE_MISALIGNMENT可以表示为STATUS_STACK_MISALIGNMENT,这将更有帮助.但随后将STATUS_DATATYPE_MISALIGNMENT转换为ERROR_NOACCESS – 这实际上掩盖并误导了问题是什么.非常无益.

感谢大家发布的建议.即使我不同意这些建议,它们也促使我在各方面进行测试(包括我不同意的方向).

写下数据类型错位问题的更详细描述:64 bit porting gotcha #1! x64 Datatype misalignment.

解决方法

64位产生差异的唯一原因是64位线程需要64位对齐值.如果threadID不是64位对齐,则可能导致此问题.

好的,这个想法不是它.你确定在main / WinMain之前调用CreateThread是有效的吗?它可以解释为什么它在菜单中起作用 – 因为它在main / WinMain之后.

另外,我会三次检查myParam的生命周期. CreateThread在调用传入的函数之前很久就会返回(我从经验中知道).

发布线程例程的代码(或只是几行).

它突然发生在我身上:您确定要将64位代码注入64位进程吗?因为如果你有一个64位的CreateThread调用并尝试将其注入到在WOW64下运行的32位进程中,则可能会发生错误.

开始认真地用尽了想法.编译器是否报告任何警告?

错误可能是由于主机程序中的错误,而不是DLL?还有一些其他代码,例如在使用__declspec(导入/导出)时加载DLL,它发生在main / WinMain之前.例如,如果该DLLMain有错误.

大佬总结

以上是大佬教程为你收集整理的CreateThread()在64位Windows上失败,在32位Windows上运行.为什么?全部内容,希望文章能够帮你解决CreateThread()在64位Windows上失败,在32位Windows上运行.为什么?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。