除了代码本身可以直接访问内存的事实.使用"/ unsafe"编译器标志和"fixed"关键字的其他含义是什么?是否存在与我的.exe的代码签名和部署相关的影响(我的应用程序仅限桌面)?
(这不是关于我是否应该这样做,为什么我的问题在这里讨论)
我理解不安全的代码更适合访问Windows API之类的东西并进行不安全的类型转换,而不是编写更高性能的代码,但我想问你是否注意到使用它时在实际应用程序中有任何显着的性能改进与安全的c#代码相比.
我正在使用以下代码在C#中制作图像蒙版:
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
bmp.SetPixel(x,y,Color.White);
}
}
for(int x = left; x < width; x++)
{
for(int y = top; y < height; y++)
{
bmp.SetPixel(x,y,Color.Transparent);
}
}
Run Code Online (Sandbox Code Playgroud)
但这太慢了......与此相比,不安全的是什么?它会分配得更快吗?
最后我用PNG格式做了一个bmp.Save().
更新:
按照MusiGenesis的建议阅读http://www.bobpowell.net/lockingbits.htm后,我使用以下代码(适用于需要它的任何人)使其工作:
Bitmap bmp = new Bitmap(1000,1000,PixelFormat.Format32bppArgb);
BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width,bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);
int PixelSize=4;
unsafe
{
for(int y=0; y<bmd.Height; y++)
{
byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);
for(int x=0; x<bmd.Width; x++)
{ …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个byte长度为s 的数组UInt32.MaxValue.这个数组本质上是一个小的(ish)内存数据库:
byte[] countryCodes = new byte[UInt32.MaxValue];
Run Code Online (Sandbox Code Playgroud)
但是,在我的机器上,在运行时,我得到一个System.OverflowException"算术运算导致溢出".
这是怎么回事?我需要使用unsafe块malloc吗?我怎么会在C#中做到这一点?
我们必须与本机代码交互很多,在这种情况下,使用不需要封送的不安全结构会快得多.但是,当结构包含非原始类型的固定大小缓冲区时,我们无法执行此操作.为什么C#编译器要求固定大小的缓冲区只是原始类型?为什么固定大小的缓冲区不能由结构组成,例如:
[StructLayout(LayoutKind.Sequential)]
struct SomeType
{
int Number1;
int Number2;
}
Run Code Online (Sandbox Code Playgroud) 这个函数的实现是什么:
fn unbox<T>(value: Box<T>) -> T {
// ???
}
Run Code Online (Sandbox Code Playgroud)
文档中唯一看起来像我想要的功能Box::into_raw.以下将进行类型检查:
fn unbox<T>(value: Box<T>) -> T {
*value.into_raw()
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误error[E0133]: dereference of raw pointer requires unsafe function or block.将其包装在一个unsafe { ... }块中可以修复它.
fn unbox<T>(value: Box<T>) -> T {
unsafe { *value.into_raw() }
}
Run Code Online (Sandbox Code Playgroud)
这是正确的实施吗?如果是这样,为什么它不安全?这是什么意思?
也许这个问题显示了我对如何Box实际工作的一般不确定性.
在回答他自己有争议的问题时,Mash已经说明你不需要"unsafe"关键字直接读写任何.NET对象实例的字节.您可以声明以下类型:
[StructLayout(LayoutKind.Explicit)]
struct MemoryAccess
{
[FieldOffset(0)]
public object Object;
[FieldOffset(0)]
public TopBytes Bytes;
}
class TopBytes
{
public byte b0;
public byte b1;
public byte b2;
public byte b3;
public byte b4;
public byte b5;
public byte b6;
public byte b7;
public byte b8;
public byte b9;
public byte b10;
public byte b11;
public byte b12;
public byte b13;
public byte b14;
public byte b15;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以做一些事情,比如改变一个"不可变"的字符串.以下代码在我的机器上打印"bar":
string foo = "foo";
MemoryAccess mem = …Run Code Online (Sandbox Code Playgroud) 我在我的.Net核心应用程序中使用了一些不安全的代码.为此,我在project.json文件中进行了此更改
"compilationOptions": {
"allowUnsafe": true,
}
这个错误仍然存在 error CS0227: Unsafe code may only appear if compiling with /unsafe
我已经经历过这个了
我需要编写一个测试来验证我的代码可以处理AccessViolationException(或任何其他WIN32损坏状态异常 - CSE),它通常通过调用第三方库来处理不安全的上下文.这应该都是使用C#on .net 4.0完成的.
我发现了这个相关的问题如何处理AccessViolationException和这篇相关的文章http://dotnetslackers.com/articles/net/All-about-Corrupted-State-Exceptions-in-NET4.aspx,它解释了如何捕获这些CSE和他们的背景.
所以我想在测试中激发一个WIN32 CSE,以确保在我的应用程序中正确处理.就像是:
一些要测试的示例类:
public class MyExceptionHandler
{
[HandleProcessCorruptedStateExceptions]
public void HandleCorruptedStateException()
{
try
{
//Force genuine unsafe AccessViolationException
//not just a throw new AccessViolationException
}
catch(Exception e)
{
//Log/cleanup/other
}
}
public void DoesNotHandleCorruptedStateException()
{
try
{
//Force genuine unsafe AccessViolationException
//not just a throw new AccessViolationException
}
catch (Exception e)
{
//Log/cleanup/other
}
}
}
Run Code Online (Sandbox Code Playgroud)
一个测试:
class MyTest
{
[Test]
public void ShouldVerifyThatAnAccessViolationExceptionIsHandledCorrectly()
{
var handler = new MyExceptionHandler(); …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
class Program
{
private unsafe static void SquarePtrParam(int* input)
{
*input *= *input;
}
private static void SquareRefParam(ref int input)
{
input *= input;
}
private unsafe static void Main()
{
int value = 10;
SquarePtrParam(&value);
Console.WriteLine(value);
int value2 = 10;
SquareRefParam(ref value2);
Console.WriteLine(value2);
//output 100, 100
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
将指针和ref关键字作为参数传递给方法有什么区别?