简体   繁体   English

为什么Microsoft错误消息使用“令牌”一词?

[英]Why Microsoft Error Message uses the word “Token”?

I purposely set a bad path for a CreateDirectory call so that my exception handling code would execute: 我故意为CreateDirectory调用设置一个错误的路径,以便我的异常处理代码将执行:

Microsoft错误文本

I am not sure if this is off topic, but you might have more experience with this. 我不确定这是不是主题,但你可能有更多的经验。 Why is the error text: 为什么是错误文本:

An attempt was made to reference a token that does not exist. 尝试引用不存在的令牌

Why are they using the word token instead of file or folder ? 他们为什么使用令牌而不是文件文件夹

I will close the question if off topic. 如果偏离主题我会关闭这个问题。

The return value of GetLastError is: 123 GetLastError的返回值是: 123

According to here : 根据这里

ERROR_INVALID_NAME

123 (0x7B)

The filename, directory name, or volume label syntax is incorrect. 文件名,目录名或卷标语法不正确。

Now that message makes sense. 现在这个消息是有道理的。 So why is my Windows 10 showing the other message? 那么为什么我的Windows 10会显示另一条消息?

There is no issue with the call to FormatMessage . 调用FormatMessage没有问题。 It works as advertised. 它像宣传的那样工作。 However, you aren't passing in the value 123 ( ERROR_INVALID_NAME ). 但是,您没有传入值123( ERROR_INVALID_NAME )。 You are passing 1008 ( ERROR_NO_TOKEN ), by accident, due to calling GetLastError at the wrong time. 由于在错误的时间调用GetLastError ,您偶然传递1008( ERROR_NO_TOKEN )。 GetLastError has a strong requirement: GetLastError有一个强烈的要求:

You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. 当函数的返回值指示此类调用将返回有用数据时,应立即调用GetLastError函数。 That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function. 这是因为一些函数在成功时调用SetLastError为零,消除了最近失败的函数设置的错误代码。

It's fairly straightforward to satisfy this in C. With C++, things get more complicated, with all the invisible code the compiler generates. 在C语言中满足这一点是相当简单的。使用C ++,事情变得更复杂,编译器生成的所有不可见代码。 The code in question apparently captures the calling thread's last error code only after it enters the CWin32FileError c'tor. 有问题的代码显然只在它进入CWin32FileError c'tor之后才捕获调用线程的最后一个错误代码。 That's too late. 那太晚了。

Based on the assumption that GetWorkingPath() returns a CString instance by value, and CWin32FileError takes its arguments as CString const& , this is what happens behind the scenes: 基于GetWorkingPath()按值返回CString实例的假设, CWin32FileError将其参数作为CString const& ,这就是幕后发生的事情:

if (!CreateDirectory(GetWorkingPath() + _T("whatever"), nullptr))
  1. GetWorkingPath() constructs a temporary CString instance. GetWorkingPath()构造一个临时的CString实例。
  2. operator+(CString const&, LPCTSTR) constructs yet another temporary CString instance, concatenating both inputs. operator+(CString const&, LPCTSTR)构造另一个临时CString实例,连接两个输入。
  3. operator LPCTSTR() is implicitly invoked on the temporary constructed in step 2. 在步骤2中构造的临时函数上隐式调用operator LPCTSTR()
  4. CreateDirectory is called and returns. CreateDirectory被调用并返回。
  5. Important: The destructor of the temporary created in step 2 is called. 重要说明:调用在步骤2中创建的临时的析构函数。
  6. Important: The destructor of the temporary created in step 1 is called. 重要:调用在步骤1中创建的临时的析构函数。

Steps 5 and 6 are fatal already, potentially changing the calling thread's last error code. 步骤5和6已经致命,可能会更改调用线程的最后一个错误代码。 And yet, there's even more code getting in the way: 然而,还有更多的代码阻碍了它们:

CWin32FileError e(_T("whatever"),
                  GetWorkingPath() + _T("whatever"));
  1. Important: _T("whatever") triggers CString 's conversion constructor ( CString(LPCTSTR) ), producing a temporary. 重要: _T("whatever")触发CString的转换构造函数( CString(LPCTSTR) ),产生一个临时的。
  2. Important: GetWorkingPath() constructs a temporary, invoking CString 's copy-c'tor. 重要: GetWorkingPath()构造一个临时的,调用CString的copy-c'tor。
  3. Important: operator+(CString const&, LPCTSTR) constructs yet another temporary. 重要: operator+(CString const&, LPCTSTR)构造了另一个临时的。
  4. The CWin32FileError c'tor finally runs, presumably calling GetLastError . CWin32FileError c'tor最终运行,大概是调用GetLastError

This adds another 3 candidates (at least) that can modify the calling thread's last error code. 这增加了另外3个候选者(至少)可以修改调用线程的最后一个错误代码。 To solve this, you're going to have to make sure, that absolutely no code runs in between a failed Windows API call and the call to GetLastError . 要解决这个问题,您必须确保在失败的Windows API调用和对GetLastError的调用之间绝对没有代码运行。

To do this, you're going to have to get rid of the temporaries, and move capturing of the last error code outside the CWin32FileError c'tor. 要做到这一点,你将不得不摆脱临时,并移动CWin32FileError c'tor之外的最后一个错误代码。 A simple solution to the former would be to construct the path name up front, eg 对前者的简单解决方案是预先构造路径名称,例如

auto path_name{ GetWorkingPath() + _T("whatever") };
auto path_name_strptr{ path_name.GetString() };
if (!CreateDirectory(path_name_strptr, nullptr))
// ...

(or use an init-statement in the if statement to limit the scope, if you are using C++17). (或者,如果使用的是C ++,则在if语句中使用init 语句来限制范围)。 Either way, your very next call must be GetLastError to capture the last error code while it is still meaningful. 无论哪种方式,您的下一个调用必须是GetLastError以捕获最后一个错误代码,同时它仍然有意义。 However you pass that value into CWin32FileError 's c'tor, or which argument types it uses, is up to you. 但是,您将该值传递给CWin32FileError的c'tor,或者它使用的参数类型取决于您。 But you cannot rely on that c'tor to capture the last error code for you. 但你不能依靠那个c'tor来捕获你的最后一个错误代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 运行 Microsoft Word 抛出 windows 服务错误 - run Microsoft Word throw windows service Error 为什么PostThreadMessage()给我一个未列出的错误消息ERROR_MESSAGE_SYNC_ONLY? - Why is PostThreadMessage() giving me an unlisted error message ERROR_MESSAGE_SYNC_ONLY? 为什么 D2D1CreateFactory 在程序集中发送错误消息 - Why is D2D1CreateFactory Sending an error message in assembly Microsoft在Excel中使用的PDF库是否可供外界使用? - Is the PDF library that Microsoft uses in Excel available to the outside world? 为什么错误消息会暂停代码。 以及如何阻止代码在 C++ 中的错误消息处暂停? - Why does an error message pause code. and how can you stop the code from pausing at the error message in C++? 微软的CopyFileEx错误 - Microsoft's CopyFileEx error 为什么这个琐碎的 opengl 程序使用 100% cpu? - Why this trivial opengl program uses 100% cpu? 为什么winapi的BOOLEAN使用1表示true,使用2表示false? - why BOOLEAN of winapi uses 1 for true and 2 for false? 如何获得Microsoft Word文档的准确窗口位置? - How to get accurate window position of Microsoft Word document? 如何将字符串发送到其他应用程序,包括Microsoft Word - How to send a string to other application including Microsoft Word
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM