如何解决不安全代码对安全代码有影响吗?
| 据我了解,将方法标记为不安全将禁用对该代码的某些CLR检查,但这会对安全的系统其余部分产生任何影响,但无法在DLL / EXE中运行一个不受信任的环境。 特别是, 它们是否是由于被标记为不安全而无法在完整dll上使用的任何安全检查? 如果DLL被标记为不安全,但是标记为不安全的方法是 未实际调用,是否与DLL被标记为相同? 安全? 在将不安全的代码保留在其中时,它们是否对运行时有好处? 单独的DLL? 我在重新绘制64位窗口上的嵌套控件时遇到了问题,如此处所述,解决方案之一(似乎可行)涉及不安全的代码,我想了解添加此代码对我的项目的影响。解决方法
您的问题的答案是:关键字
unsafe
并不表示\“不安全\”,而是表示\“潜在不安全\”。编译器和框架无法确保其安全性。由您确定代码不能执行不安全的读取或写入内存。
我强烈建议您遵循所链接文章中的建议:
1)重新设计应用程序,以减少容器数量并减少嵌套级别。
如果您仅将容器用于控制布置,请编写自己的容器,该容器可以一层完成所有布置。
更新
您可以修改该文章中的代码,使其不使用指针(即不需要unsafe关键字)。请记住,这现在需要进行编组,这意味着需要额外的复制。这可能是一件好事,因为原始代码正在将WINDOWPOS指针从操作系统传递到BeginInvoke,该指针在操作系统生成指针的同一调度事件中不会执行。换句话说,该代码已经很臭了。
internal class MyTabPage : TabPage
{
private const int WM_WINDOWPOSCHANGING = 70;
private const int WM_SETREDRAW = 0xB;
private const int SWP_NOACTIVATE = 0x0010;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
[DllImport(\"User32.dll\",CharSet = CharSet.Auto)]
extern static int SendMessage(HandleRef hWnd,int msg,int wParam,int lParam);
[DllImport(\"User32.dll\",ExactSpelling = true,CharSet = System.Runtime.InteropServices.CharSet.Auto)]
extern static bool SetWindowPos(HandleRef hWnd,HandleRef hWndInsertAfter,int x,int y,int cx,int cy,int flags);
[StructLayout(LayoutKind.Sequential)]
private class WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
};
private delegate void ResizeChildDelegate(WINDOWPOS wpos);
private void ResizeChild(WINDOWPOS wpos)
{
// verify if it\'s the right instance of MyPanel if needed
if ((this.Controls.Count == 1) && (this.Controls[0] is Panel))
{
Panel child = this.Controls[0] as Panel;
// stop window redraw to avoid flicker
SendMessage(new HandleRef(child,child.Handle),WM_SETREDRAW,0);
// start a new stack of SetWindowPos calls
SetWindowPos(new HandleRef(child,new HandleRef(null,IntPtr.Zero),wpos.cx,wpos.cy,SWP_NOACTIVATE | SWP_NOZORDER);
// turn window repainting back on
SendMessage(new HandleRef(child,1,0);
// send repaint message to this control and its children
this.Invalidate(true);
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_WINDOWPOSCHANGING)
{
WINDOWPOS wpos = new WINDOWPOS();
Marshal.PtrToStructure(m.LParam,wpos);
Debug.WriteLine(\"WM_WINDOWPOSCHANGING received by \" + this.Name + \" flags \" + wpos.flags);
if (((wpos.flags & (SWP_NOZORDER | SWP_NOACTIVATE)) == (SWP_NOZORDER | SWP_NOACTIVATE)) &&
((wpos.flags & ~(SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) == 0))
{
if ((wpos.cx != this.Width) || (wpos.cy != this.Height))
{
BeginInvoke(new ResizeChildDelegate(ResizeChild),wpos);
return;
}
}
}
base.WndProc(ref m);
}
}
注意:WINDOWPOS从值类型更改为引用类型是有意的。使用引用类型会将副本数量减少到仅一个(初始元帅)(**)。
再次更新
我只是注意到该代码最初使p / invoke声明公开。永远不要在类(*)之外公开p / invoke。如果您打算公开提供的功能,请编写调用私有p / invoke声明的托管方法。在这种情况下是不正确的,p /调用严格是内部的。
(*)好,一个例外。您正在创建NativeMethods
,UnsafeNativeMethods
等。这是FxCop推荐的p / invoke方法。
更新
(**)我被要求(在其他地方)准确地描述为什么在这里使用引用类型更好,所以我在这里添加了该信息。我被问到的问题是:“这是否增加了内存压力?”
如果“ 4”是一个值类型,则将是事件序列:
1)从非托管内存复制到托管内存
WINDOWPOS wpos = Marshal.PtrToStructure(m.LParam,typeof(WINDOWPOS));
2)第二份?
BeginInvoke(new ResizeChildDelegate(ResizeChild),wpos);
等待! BeginInvoke
的签名是(Delegate,params object[])
。这意味着wpos将被装箱。因此,是的,第二个副本出现在这里:装箱操作。
BeginInvoke
将委托和对象[]添加到调用列表中并发布注册的窗口消息。当消息泵从队列中删除该消息时,将使用object []参数调用该委托。
3)取消装箱并复制以进行ResizeChild
通话。
在这一点上,您可以看到副本数甚至不是问题。将其转换为引用类型(带框)的事实意味着我们最好将其设置为引用类型。
,不安全的代码可能会破坏托管堆。这样,在同一进程中运行的任何内容都会受到影响。
这包括同一过程中的所有其他库以及可能的所有其他AppDomain。
更新
这是一个例子:
http://blogs.msdn.com/b/tess/archive/2006/02/09/net-crash-managed-heap-corruption-calling-unmanaged-code.aspx
更新2
是编写的不安全代码
努力地坏吗?
不会。.NET框架本身中有大量不安全的代码。示例很多,但这是here11中的一个:
public static unsafe string Copy(string str)
{
if (str == null)
{
throw new ArgumentNullException(\"str\");
}
int length = str.Length;
string str2 = FastAllocateString(length);
fixed (char* chRef = &str2.m_firstChar)
{
fixed (char* chRef2 = &str.m_firstChar)
{
wstrcpyPtrAligned(chRef,chRef2,length);
}
}
return str2;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。