我用一种结构来表示纯数据.其中一个字段是固定大小的缓冲区,如下所示.
[StructLayout(LayoutKind.Sequential, Pack=2)]
unsafe struct ImageDosHeader
{
...
private fixed ushort _e_res[4];
...
[Description("Reserved")]
[DisplayName("e_res[0]")]
public ushort e_res_0 { get { ... } set { ... } }
...
}
Run Code Online (Sandbox Code Playgroud)
在get/set函数中,我尝试执行以下操作,但是我得到"编译器错误CS1666:您不能使用包含在未固定表达式中的固定大小缓冲区.请尝试使用fixed语句."
return this._e_res[0];
Run Code Online (Sandbox Code Playgroud)
但是,以下工作:
fixed (ImageDosHeader* p = &this)
return p->_e_res[0];
ImageDosHeader local = this;
return local._e_res[0];
Run Code Online (Sandbox Code Playgroud)
我可以轻松地使用变通方法,但是,我想知道为什么直接从这里访问固定大小的缓冲区是非法的.或者这是我应该报告的错误?
我使用的是.NET 2.0.
我正在部署一个程序,代码库是C++/CLI和C#的混合体.C++/CLI有各种风格:native,mixed(/clr)和safe(/clr:safe).在我的开发环境中,我创建了一个包含所有C++/CLI代码的DLL,并从C#代码(EXE)引用它.这种方法完美无瑕.
对于我的发行版,我想发布一个可执行文件(只是声明"为什么不只是将DLL和EXE分开?"是不可接受的).
到目前为止,我已经成功地用所有不同的来源编译EXE.但是,当我运行它时,我得到"XXXX已停止工作"对话框,其中包含检查在线,关闭和调试的选项.问题详情如下:
Problem Event Name: APPCRASH
Fault Module Name: StackHash_8d25
Fault Module Version: 6.1.7600.16559
Fault Module Timestamp: 4ba9b29c
Exception Code: c0000374
Exception Offset: 000cdc9b
OS Version: 6.1.7600.2.0.0.256.48
Locale ID: 1033
Additional Information 1: 8d25
Additional Information 2: 8d25552d834e8c143c43cf1d7f83abb8
Additional Information 3: 7450
Additional Information 4: 74509ce510cd821216ce477edd86119c
Run Code Online (Sandbox Code Playgroud)
如果我调试并将其发送到Visual Studio,它会报告:
Unhandled exception at 0x77d2dc9b in XXX.exe: A heap has been corrupted
Run Code Online (Sandbox Code Playgroud)
选择中断会导致它停在ntdll.dll!77d2dc9b(),没有其他信息.如果我告诉Visual Studio继续,程序启动正常并且似乎没有发生任何事故,可能是因为现在附加了调试器.
你是怎么做到的?如何避免这种堆损坏?该程序似乎工作正常,除此之外.
我的删节编译脚本如下(为简洁起见,我省略了错误检查):
@set TARGET=x86
@set TARGETX=x86
@set OUT=%TARGETX%
@call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" %TARGET%
@set WIMGAPI=C:\Program Files\Windows …Run Code Online (Sandbox Code Playgroud) 我正在创建一个程序来监视按键以在全球范围内控制 iTunes。它还有一些 WinForms(用于显示曲目信息和编辑选项)。
低级键盘钩子可以很好地工作一段时间。如果我刚启动该程序,键盘挂钩已设置并打开 iTunes。然后我打开记事本,可以非常快速地输入大量内容,并且每个笔画都被捕获,最多 30 毫秒用于钩子函数(并且大部分时间<10 毫秒)。钩子函数只是将事件添加到由另一个线程处理的队列中。它使用自己的 Application.Run() 在自己的高优先级线程上运行。
但是,如果我开始在 iTunes 内(例如在我的程序中生成事件的几次播放/暂停点击)或在程序内(例如打开选项窗口)开始执行操作,则挂钩函数将停止调用!即使从未使用过键盘,也可能发生这种情况(例如,在 iTunes 中启动、单击播放并暂停几次,然后按下某个键)。
钩子没有被调用的原因并不是因为在钩子函数中花费了太多时间。
当我调用 UnhookWindowsHookEx 时,它总是返回 true,无论钩子函数是否仍在被调用。
那么,可能是什么原因呢?
一个想法(尽管我没有证据或解决方案)是托管线程不再是正确的本机线程。我在我的程序中使用了许多(托管)线程,并且我读到单个本机线程可以运行许多托管线程,并且托管线程可以更改正在运行它的本机线程。钩子是否可能仍在生成消息但将它们发送到错误的线程?如果是这种情况,我该如何解决?
编辑:钩子和回调
我的 KeyMonitor 的一个稍微精简的版本。为了清楚起见,它被剥离了。我已经删除了一些实用程序(如 Key 枚举的大多数值和 Keys 类的许多函数,如 ToString() 和 FromString())以及一些错误处理。
大多数重要的东西都在 KeyMonitor 类中。KeyMonitor.Start() 为消息启动一个线程, KeyMonitor.HookThread() 是该线程,并为消息循环创建钩子和 Application.Run(), KeyMonitor.KeyboardHookProc() 是回调函数,KeyMonitor。 HookEventDispatchThread() 用于调度回调记录的事件。
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace KeyTest
{
enum Key : int
{
Shift = 0x10, Ctrl, Alt,
Left_Win = 0x5B, Right_Win,
Left_Shift = 0xA0, Right_Shift, Left_Ctrl, Right_Ctrl, Left_Alt, Right_Alt,
} …Run Code Online (Sandbox Code Playgroud) 反正只有一个项目无效ListBox吗?似乎没有获取项目矩形的方法,或者即使特定项目可见(除了调用IndexFromPoint控件中的每个像素/至少一列中的每个像素).
这适用于C#WinForms(不是WPF).
有关我要做的事情的更多信息:
我有一个ListBox包含很多项目的东西,我希望在你悬停的项目上出现一组"按钮"(例如红色的X用于删除).我有这个工作很好,除了在10个或更多项目的列表上,每次你将鼠标悬停在一个新项目上它会导致可见的重绘,因为我使整个控件无效.数据不会更改,只会更改显示.
编辑:更多信息和以前的尝试
我已经子类化ListBox并执行我的绘图,OnDrawItem因此ListBox可以使用受保护的方法.
我尝试了以下不同程度的成功.变量this是扩展的ListBox,index是要绘制old_index的项目,是先前被绘制的项目.
// Causes flicker of entire list, but works
this.Invalidate();
// Causes flicker of selected item, but works
int sel_index = this.SelectedIndex;
this.SelectedIndex = old_index;
this.SelectedIndex = index;
this.SelectedIndex = sel_index;
// Does not work
if (old_index >= 0)
this.RefreshItem(old_index);
if (index >= 0)
this.RefreshItem(index);
Run Code Online (Sandbox Code Playgroud) 我有一个返回大型NumPy数组的类。这些数组被缓存在类中。我希望返回的数组是写时复制数组。如果调用者最终只是从数组中读取,则不会进行任何复制。这样可以避免使用多余的内存。但是,该数组是“可修改的”,但不会修改内部缓存的数组。
目前,我的解决方案是将所有缓存的数组设置为只读(a.flags.writeable = False)。这意味着,如果函数的调用者想要修改数组,则可能必须制作自己的数组副本。当然,如果源不是来自缓存,并且阵列已经可写,则它们将不必要地复制数据。
因此,最理想的情况是我喜欢这样的东西a.view(flag=copy_on_write)。似乎有个相反的标志,UPDATEIFCOPY一旦释放,副本就会更新原件。
谢谢!
使用variadic模板模板参数时,要使用sizeof获取参数数量(...)GCC和Clang有不同的要求.GCC要求您填写可变参数的模板参数,而Clang要求您不要这样做.由于它们都声称符合标准,因此必须有错误或标准必须含糊不清(如果它们应在c ++ 1y中更正).
示例(http://ideone.com/5TWFKY上的完整可编辑示例):
template<template <class> class... T>
struct X
{
/* code goes here */
};
Run Code Online (Sandbox Code Playgroud)
GCC(注意:在这种情况下,Z是任何非模板类):
static const constexpr size_t count = sizeof...(T<Z>);
Run Code Online (Sandbox Code Playgroud)
铛:
static const constexpr size_t count = sizeof...(T);
Run Code Online (Sandbox Code Playgroud)
MSVC 2013(完整性 - 与Clang w/out constexpr相同,不支持):
static const size_t count = sizeof...(T);
Run Code Online (Sandbox Code Playgroud)