缩小这个问题的范围真的很难,但我们开始吧。
我处于加载到主机 (TstCon.exe) 的 32 位 ActiveX 控件的上下文中。卸载并重新加载控件后,我从 NtMapViewOfSection 收到一连串错误,第一个错误发生在 odbc32.dll 使用 LoadLibraryExW 加载时C:\Windows\system32\odbcint.dll。那时,SEH 异常从 NtMapViewOfSection 内部某处发出,代码为 0xC0000023(根据调试器也称为 STATUS_BUFFER_TOO_SMALL)。
这是调试器拦截异常时调用堆栈的样子:
ntdll.dll!_NtMapViewOfSection@40()
KernelBase.dll!BasepLoadLibraryAsDataFileInternal()
KernelBase.dll!BasepLoadLibraryAsDataFile()
KernelBase.dll!LoadLibraryExW()
odbc32.dll!_InitializeDll@0()
odbc32.dll!_SQLAllocEnv@4()
<OurDll>.dll!<OurFunction>()
...
那时,我已经使用非常理智的技术来检索调用NtMapViewOfSection 的参数,方法是遵循this documentation。 :
*(void**)(ESP + 4 + 0) /*SectionHandle*/ 0x000003b0 void *
*(void**)(ESP + 4 + 4) /*ProcessHandle*/ 0xffffffff void *
*(void**)(ESP + 4 + 8) /*BaseAddress*/ 0x00daae30 void *
*(unsigned long*)(ESP + 4 + 12) /*ZeroBits*/ 0x00000000 unsigned long
*(unsigned long*)(ESP + 4 + 16) /*CommitSize*/ 0x00000000 unsigned long
*(long long**)(ESP + 4 + 20) /*SectionOffset*/ 0x00000000 {???} __int64 *
*(unsigned long**)(ESP + 4 + 24) /*ViewSize*/ 0x00daae28 {0x00000000} unsigned long *
*(int*)(ESP + 4 + 28) /*InheritDisposition*/ 0x00000001 int
*(unsigned long*)(ESP + 4 + 32) /*AllocationType*/ 0x00800000 unsigned long
*(unsigned long*)(ESP + 4 + 36) /*Protect*/ 0x00000002 unsigned long
我最初是通过在 VS 的调试器中启用 break-on-throw 来捕获异常的,然后我就能够查明第一个失败的调用并在前面放置一个断点。这是我在反汇编内部进行调试时可以看到的内容(> 标记当前指令):
_NtMapViewOfSection@40:
76F2EF60 mov eax,28h
76F2EF65 mov edx,offset _Wow64SystemServiceCall@0 (76F43430h)
> 76F2EF6A call edx
76F2EF6C ret 28h
76F2EF6F nop
...进入:
_Wow64SystemServiceCall@0:
> 76F43430 jmp dword ptr [_Wow64Transition (76FD2218h)]
...进入:
> 74A37000 jmp 0033:74A37009
74A37007 add byte ptr [eax],al
74A37009 inc ecx
74A3700A jmp dword ptr [edi+0F8h]
...进入:
_NtQueryObject@20:
76F2EDC0 mov eax,10h
76F2EDC5 mov edx,offset _Wow64SystemServiceCall@0 (76F43430h)
76F2EDCA call edx
> 76F2EDCC ret 14h
76F2EDCF nop
下一个进入会触发异常。
对程序环境的干扰,例如:
/base 链接器标志强制 OCX 的基地址;drstrace.exe 监控系统调用;... 更改对 NtMapViewOfSection 的调用将成功或失败,似乎是随机的:并非所有调用都失败,但有相当一部分会失败。事实上,错误的第一次出现可能并不能说明问题的实际来源,因为我很少能够使它更早地崩溃(在卸载控件时),甚至在 none 的情况下发生崩溃 我们的代码在调用堆栈上(通过直接退出 TstCon.exe)。
我找不到任何文档(官方或其他)提及 STATUS_BUFFER_TOO_SMALL 或在此上下文中的 0xC0000023 代码。我一直无法在失败的调用中找到模式,并且在 Dr. Memory 运行中没有看到相关的访问错误。
那么......这个过程中可能发生了什么导致出现这种症状?
最佳答案
在长时间检查 ActiveX 控件的执行后,使用调试器跳过特定的代码部分,我将错误的可能位置缩小到单个函数。事实证明,问题的根源几乎无法猜测。
有一天,有人希望能够为线程命名。为此,他们使用了记录在案的 0x406D1388技术(事实上,代码几乎是从链接文档中复制粘贴的)。这本身就很好。但是后来他们想要(或者我收集到)以编程方式检索名称,自定义异常方法不支持。这一切都是在 SetThreadDescription/GetThreadDescription 存在之前发生的,所以他们寻找另一种方法。 男人他们有创造力。
除了对抛出自定义异常的函数的调用之外,还有以下几行:
// Grab the TIB.
P_T_TIB pTib = GetTIB();
if (pTib == NULL)
return false;
// If someone has already written to the arbitrary field, I don't
// want to be overwriting it.
if (pTib->pvArbitrary == NULL)
{
// Nothing's there. Set the name.
pTib->pvArbitrary = (void *)pszName;
}
有什么,当然绝对不是“无”。 GetTIB定义如下:
// A static function to get the TIB.
static P_T_TIB GetTIB()
{
P_T_TIB pTib = NULL;
_asm
{
MOV EAX, FS:[18h]
MOV pTib, EAX
}
return pTib;
}
据我所知,这段高度可疑的程序集检索了一个指向 Thread Information Block 的指针。当前线程的。 T_TIB 的定义遵循该页面上的描述,并允许线程命名函数将指向名称的指针存储到任意数据槽中。在名称获取函数中使用了相同的技术来检索指针并返回名称。
当然,难点在于“任意”并不代表“用户数据”,NtMapViewOfSection和小伙伴们都是依赖字段来存储信息的,字段上放置的数据断点就是明证被 LdrpMapViewOfSection 等击中。在他们路径的某个地方,遇到具有异常非零值(即我们的名称指针)的字段导致他们执行一些非常错误的操作,最终触发了那个奇怪的异常。
出于好奇,我完全删除了所有这些,因为它没有在其他任何地方使用,并且只是使用了一个 thread_local 变量来存储名称。结案了!
关于c++ - `LoadLibraryExW` 从 `0xC0000023` 触发异常 `NtMapViewOfSection`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53767707/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我有一个rubyonrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素
我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d