不安全代码对安全代码有影响吗?

问题描述

| 据我了解,将方法标记为不安全将禁用对该代码的某些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;
}
    

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...