我们有一个针对DirextX 7 SDK编程的软件(即代码使用 LPDIRECTDRAWSURFACE7
等)并全屏运行.主要任务是以可靠的方式在屏幕上放置一些内容以响应外部触发器.这在Windows XP上表现得非常好:通常软件会等待一些触发器,当触发时,会创建一个新帧,将其放入后备缓冲区,然后告诉DX翻转缓冲区.结果是触发器和屏幕上有效显示帧之间的近似延迟,取决于视频卡和驱动程序,对于60Hz屏幕,3帧或50毫秒.这是在各种系统上测试的,都运行NVidia卡.在一些具有较高端卡的系统上,我们甚至可以获得2帧.
但是,在Windows 7上运行相同的软件时(根本没有安装其他软件),我们不能低于5帧.在管道中的某个地方,操作系统或驱动程序或两者都需要2个额外的帧,这几乎是应用程序无法接受的.我们尝试禁用航空/桌面组合/不同的驱动程序版本/不同的视频卡但无济于事.
在这里编辑一些似乎相关的代码:
创建前/后表面:
ddraw7->SetCooperativeLevel( GetSafeHwnd(),
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_MULTITHREADED )
DDSURFACEDESC2 desc;
ZeroMemory( &desc, sizeof(desc) );
desc.dwSize = sizeof( desc );
desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE |
DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
desc.dwBackBufferCount = 1;
ddraw7->CreateSurface( &desc, &primsurf, 0 )
DDSCAPS2 surfcaps;
ZeroMemory( &surfcaps,sizeof( surfcaps ) );
surfcaps.dwCaps = DDSCAPS_BACKBUFFER;
primsurf->GetAttachedSurface( &surfcaps, &backsurf );
Run Code Online (Sandbox Code Playgroud)
创建用于在绘制帧之前渲染帧的曲面:
DDSURFACEDESC2 desc;
ZeroMemory( …
Run Code Online (Sandbox Code Playgroud) 昨天我在相当简单的代码中发现了一个奇怪的错误,它基本上从ifstream获取文本并将其标记化.实际失败的代码会执行许多get()/ peek()调用以查找令牌"/*".如果在流中找到令牌,则调用unget(),以便下一个方法看到以令牌开头的流.
有时,看似仅依赖于文件的长度,unget()调用失败.在内部它调用pbackfail()然后返回EOF.但是在清除流状态之后,我可以愉快地阅读更多字符,因此它不完全是EOF.
在深入研究之后,这里是完整的代码,可以轻松地重现问题:
#include <iostream>
#include <fstream>
#include <string>
//generate simplest string possible that triggers problem
void GenerateTestString( std::string& s, const size_t nSpacesToInsert )
{
s.clear();
for( size_t i = 0 ; i < nSpacesToInsert ; ++i )
s += " ";
s += "/*";
}
//write string to file, then open same file again in ifs
bool WriteTestFileThenOpenIt( const char* sFile, const std::string& s, std::ifstream& ifs )
{
{
std::ofstream ofs( sFile );
if( ( ofs << s …
Run Code Online (Sandbox Code Playgroud) 这里的输出git log
:
* 5a831fdb34f05edd62321d1193a96b8f96486d69 HEAD (HEAD, origin/work, work)
| LIB/xxx.cpp | Bin 592994 -> 593572 bytes
| LIB/xxx.h | 5 +++++
| LIB/bbb/xxx.h | 9 +++++++++
| LIB/aaa/xxx.cpp | Bin 321534 -> 321536 bytes
| LIB/aaa/yyy.cpp | 31 +++++++------------------------
| tests/aaa/xxx.cpp | 29 +++++++++++++++++++++++++++++
| tests/test_xxx.vcproj | 4 ++++
| 7 files changed, 54 insertions(+), 24 deletions(-)
Run Code Online (Sandbox Code Playgroud)
为什么它将某些文件视为二进制文件,而其他文件则不是?这给出了严重的问题,因为git也不想自动合并它们.因此几乎所有的merge/rebase/pull动作都变得很痛苦.
这是repo配置:
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true …
Run Code Online (Sandbox Code Playgroud) 我在wpf中使用的所有菜单/上下文菜单/工具栏都在ViewModel代码中声明,非常类似于:
MenuService.Add( new MenuItem()
{
Header = "DoStuff",
Command = new relayCommand( DoStuff, () => CanDoStuffExecute() )
// some more properties like parent item/image/...
} );
Run Code Online (Sandbox Code Playgroud)
MenuService提供单个绑定点,它是MenuItem的分层列表,并绑定到xaml中的实际Menu的ItemsSource.
这非常有效,现在我想以同样方便的方式添加键盘快捷键.理想情况下,MenuItem将获得类型的属性,System.Windows.Input.KeyGesture
所以我可以简单地写
Shortcut = new KeyGesture( Key.D, ModifierKeys.Control )
Run Code Online (Sandbox Code Playgroud)
这会导致在拥有菜单的窗口中按Ctrl + D调用项目的命令,这也会导致在菜单中自动显示"Ctrl + D".
但是我迷失在这里:我想通过数据绑定设置MenuItem.InputBindings集合,但它是get-only.我怎么能把物品放进去呢?或者是否有一个MVVM框架已经支持这样的东西?我在键盘快捷键上找到的大多数q&a都是关于通过xaml设置快捷方式,这没有任何帮助.
更新
搜索'relaycommand vs routeduicommand和'relaycommand keygesture'等确实揭示了足够的信息来提出一个工作虽然hacky解决方案.肯定有其他更好的方法,但目前这对我来说是超低优先级,完美地完成了这项工作.我向MenuItem类添加了两个属性,如下所示:
//Upon setting a Gesture, the original command is replaced with a RoutedCommand
//since that automatically gives us proper display of the keyboard shortcut.
//The RoutedCommand simply calls back into the original Command. …
Run Code Online (Sandbox Code Playgroud) 在我开发的所有WPF应用程序中,都有一个订阅的全局异常处理程序AppDomain.CurrentDomain.UnhandledException
记录它可以找到的所有内容,然后显示一个对话框,告诉用户联系作者,日志文件在哪里等.这非常有效,客户和我对它非常满意,因为它可以快速解决问题.
但是,在开发混合的WPF/C#/ CLI/C++应用程序期间,有时应用程序崩溃无法进入上述异常处理程序.而是弹出一个标准的Windows对话框,说"XXX已停止工作".在细节中它显示了例如
Problem Event Name: BEX
Application Name: XXX.exe
Fault Module Name: clr.dll
...
Run Code Online (Sandbox Code Playgroud)
这主要发生在从非托管代码中回调托管函数时,以及该函数更新屏幕时.我没有花很长时间来找出问题的根本原因,但只是因为我可以在我的机器上重现崩溃并连接调试器:在所有情况下,本机线程仍然在调用函数指针的时候直接调用C#/ WPF代码的托管委托.
真正的问题是当这种情况发生在客户端机器上时:鉴于通常客户不是那里最好的错误记者,所以当他们能够提供给我的是上面的细节时,需要花很长时间才能找出错误.
问题是:如何获取更多类似崩溃的信息?有没有办法获得像这样的异常调用自定义错误处理程序?或者获得进程转储?加载msvcr100_clr0004.dll和clr.dll(在发生中断的线程上加载)的符号时,调用堆栈如下所示:
msvcr100_clr0400.dll!__crt_debugger_hook()
clr.dll!___report_gsfailure() + 0xeb bytes
clr.dll!_DoJITFailFast@0() + 0x8 bytes
clr.dll!CrawlFrame::CheckGSCookies() + 0x2c3b72 bytes
Run Code Online (Sandbox Code Playgroud)
我可以以某种方式将一些本机C++代码挂钩到__crt_debugger_hook()(例如,用于编写minidump)吗?这引出了一个额外的问题:如何CheckGSCookies
在没有安装调试器的机器上运行,它是否仍会调用相同的代码?
更新一些关于代码的说明:本机C++调用CLI委托(获取本机函数指针,使用GetFunctionPointerForDelegate
该委托调用C#System.Action.此Action更新字符串(绑定到WPF标签)并引发propertychanged事件这在某个未在我的代码中直接创建的未命名线程中以某种方式调用缓冲区溢出(在更新时非常快).
更新调查SetUnhandledExceptionFilter
,一开始没有做任何事情,我发现这篇漂亮的文章解释了如何捕获任何异常.它工作正常,我能够在使用该过程安装的异常过滤器中编写一个minidump.转储提供与挂钩调试器基本相同的信息:真正的问题似乎是在从ui线程读取的同时覆盖了Status字符串(通过从本机线程调用).所有这些都很好,但它确实需要dll挂钩,这不是我最喜欢的解决方法.另一种方式仍然很好.
有一个正在测试的类目前接受unique_ptr< Interface >&&
它的构造函数,表示它想要接受一个接口实现的单一所有权.当想要使用Interface
模拟测试此类时会出现问题:模拟框架(HippoMocks)仅向我提供了我Interface*
不拥有的类,因此无法删除.
在测试const shared_ptr< Interface >&
作为参数的类之前我遇到了同样的问题,但通过提供自定义的no-op删除器修复了这个问题:
template< class T >
void NoDelete( T* )
{
}
//create a shared_ptr without effective deleter
template< class T >
std::shared_ptr< T > mock_shared( T* t )
{
return std::shared_ptr< T >( t, NoDelete< T > );
}
Interface* iface = mocks.GetMeAMock< Interface >();
DoStuffWithSharedPtrOfInterface( mock_shared< Interface >( iface ) );
Run Code Online (Sandbox Code Playgroud)
对unique_ptr的类似修复并没有真正解决,因为删除器是一个模板参数:
template< class T >
struct NoDelete
{
void operator ()( T* )
{ …
Run Code Online (Sandbox Code Playgroud) 我调试,使大量使用STL的和为了不被在keyaboard整天捣按住Shift键F11应用久,我有一个my.natstepfilter文件中C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\Visualizers
包含
<?xml version="1.0" encoding="utf-8"?>
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
<Function><Name>std::.*</Name><Action>NoStepInto</Action></Function>
</StepFilter>
Run Code Online (Sandbox Code Playgroud)
据我所知,这是让VS2012不进入任何功能的方法std::
,请纠正我,如果我错了.
然而,这没有任何影响,调试器只是跳进了所有内容.此外,当使用过滤器运行procmon Visualizers
并启动调试会话时,它看起来像这样:
所以它查询正确目录中的所有内容,但继续读取所有.natvis文件,但不读取.natstepfilter文件.所以看来VS正在积极做一些事情来完全忽略过滤器.
关于如何解决这个问题或者在哪里寻找解决方案的想法?
附加信息:我有一大堆扩展加载,但它们似乎都没有与调试器有任何业务(更不用说他们告诉VS跳过过滤器文件).只是为了确保Debugger Type
明确设置Native Only
为我读到过滤器不适用于混合模式.被调试的应用程序只是本机的.尝试调试x86和x64进程.
我想将一个参数包拆分成第一个N-1和第N个参数,而不使用典型的index_sequence和tuple技巧,但似乎无法绕过它,但我很确定它应该可行吗?(通过递归获得最后一项很容易).
调用的最终函数看起来像
void Fun( Foo a, Bar b );
Run Code Online (Sandbox Code Playgroud)
并且a依次从可变参数获得:
template< class... T >
Foo CalcFoo( T... args );
Run Code Online (Sandbox Code Playgroud)
我目前的实施:
//get the last item of the pack
template< class T >
T split_last( T t ){ return t; }
template< class... T >
T split_last( T, T... t ){ return split_last( t... ); }
//helper
template< class... T, size_t... Indices >
Foo CalcFoo( const std::tuple< T... >& args, index_sequence< Indices... > )
{
return CalcFoo( std::get< Indices >( args )... …
Run Code Online (Sandbox Code Playgroud) 在我的 MSVC 2015 项目中,我有一个函数,int foo(int, int)
它在 .asm 文件中实现。当我extern "C"
在同一个项目的 .cpp 文件中声明这个函数时,Intellisense 抱怨Function definition for 'foo' not found.
:
我不知道为什么 Intellisense 认为它通常可以找到 extern 函数的定义 - 其中很多将在 dll、静态库或其他二进制格式中声明,而在编译时没有可用的源,更不用说我的 .asm (编译为 .obj 作为项目构建的一部分)文件案例。
我应该提到该项目构建良好并且foo()
被调用没有问题。
Intellisense在这方面的问题是什么,如何解决?