我一直在尝试确定在C#中使用fixed语句对于包含固定数组的托管不安全结构的真正成本.请注意我不是指非托管结构.
具体来说,有没有理由避免下面的'MultipleFixed'类显示的模式?简单地修复数据的成本是非零,接近零(==成本类似于在进入/退出固定范围时设置和清除单个标志),还是足够重要以避免在可能的情况下?
显然,这些课程是为了帮助解释这个问题而设计的.这是针对XNA游戏中的高使用率数据结构,其中此数据的读/写性能至关重要,因此如果我需要修复数组并将其传递到任何地方,我会这样做,但如果没有任何差别我我更喜欢将fixed()本地保留在方法中,以帮助保持函数签名对于不支持不安全代码的平台更加轻松.(是的,它的一些额外的咕噜声代码,但不管它需要......)
unsafe struct ByteArray
{
public fixed byte Data[1024];
}
class MultipleFixed
{
unsafe void SetValue(ref ByteArray bytes, int index, byte value)
{
fixed(byte* data = bytes.Data)
{
data[index] = value;
}
}
unsafe bool Validate(ref ByteArray bytes, int index, byte expectedValue)
{
fixed(byte* data = bytes.Data)
{
return data[index] == expectedValue;
}
}
void Test(ref ByteArray bytes)
{
SetValue(ref bytes, 0, 1);
Validate(ref bytes, 0, 1);
}
}
class SingleFixed
{
unsafe void SetValue(byte* data, int index, … 我一直在搜索C#语言规范,我找不到任何说明指针类型(例如int*)是否使用默认值初始化的内容.我创建了一个简单的测试应用程序,似乎将它们初始化为零,但我想用规范确认.
我开始寻找这个,因为我注意到在反射器中IntPtr类使用此代码来定义它IntPtr.Zero:
public struct IntPtr : ISerializable
{
private unsafe void* m_value;
public static readonly IntPtr Zero;
.......
public static unsafe bool operator ==(IntPtr value1, IntPtr value2)
{
return (value1.m_value == value2.m_value);
}
........
}
Run Code Online (Sandbox Code Playgroud)
这意味着当你与IntPtr.Zero它进行比较时,实际上是与分配给m_value具有类型的字段的默认值进行比较void*.
谢谢.
我正在开发单核嵌入式芯片。在 C 和 C++ 中,静态定义可全局使用的可变值是很常见的。Rust 的等价物大致是这样的:
\nstatic mut MY_VALUE: usize = 0;\n\npub fn set_value(val: usize) {\n unsafe { MY_VALUE = val }\n}\n\npub fn get_value() -> usize {\n unsafe { MY_VALUE }\n}\nRun Code Online (Sandbox Code Playgroud)\nget_value现在任何地方都可以调用免费函数set_value.
我认为这在单线程嵌入式 Rust 中应该是完全安全的,但我还没有找到明确的答案。我只对不需要分配或销毁的类型感兴趣(例如此处示例中的原语)。
\n我能看到的唯一问题是编译器或处理器以意想不到的方式重新排序访问(这可以使用易失性访问方法来解决),但这unsafe 本身就是问题就是这样吗?
编辑:
\n这本书表明,只要我们能保证没有多线程数据竞争,这就是安全的(显然这里就是这种情况)
\n\n\n对于全局可访问的可变数据,很难确保不存在数据竞争,这就是 Rust 认为可变静态变量不安全的原因。
\n
这些文档的措辞不太明确,表明数据竞争只是不安全的一种方式,但没有扩展到其他示例
\n\n\n访问可变静态可能会以多种方式导致未定义的行为,例如由于多线程上下文中的数据竞争
\n
秘典表明,只要您不以某种方式取消引用坏指针,这应该是安全的。
\n在我们的一个项目中,我们有类似的代码.任何人都可以解释(简单英语)为什么需要修复语句?
class TestClass
{
int iMyVariable;
static void Main()
{
TestClass oTestClass = new TestClass();
unsafe
{
fixed (int* p = &oTestClasst.iMyVariable)
{
*p = 9;
}
}
}
}
Run Code Online (Sandbox Code Playgroud) 在C#中,可以声明一个具有指针类型成员的结构(或类),如下所示:
unsafe struct Node
{
public Node* NextNode;
}
Run Code Online (Sandbox Code Playgroud)
它是否安全(错误......忽略了那个具有讽刺意味的unsafe小旗......)使用这种结构?我的意思是在堆上长期存储.根据我的理解,GC可以自由移动,当它更新对已被移动的内容的引用时,它是否也更新了指针?我猜不是,这会使这种结构非常不安全,对吧?
我确信这样做有更好的选择,但称之为病态的好奇心.
编辑:似乎有些混乱.我知道这不是一个伟大的结构,我纯粹想知道这是否是一个安全的结构,即:指针保证指向你最初指向它的东西?
原始C代码用于遍历树(深度优先)而不递归,其中树存储在数组中.然后通过递增指针遍历数组,除非满足某个条件,然后将指针设置为NextNode,其中遍历继续.当然,在C#中也可以通过以下方式实现:
struct Node
{
public int NextNode;
... // other fields
}
Run Code Online (Sandbox Code Playgroud)
其中int是下一个节点的数组中的索引.但出于性能原因,我最终会摆弄指针和fixed数组以避免边界检查,而原始的C代码似乎更自然.
目前我正在寻求在C#/ .NET中使用相当快速且合理准确的算法来在代码中执行以下步骤:
我已经说明了我想要实现的目标:

我能想象的是将像素的颜色设置为(0,0),然后unsafe逐行/逐列遍历所有像素直到我遇到另一种颜色的像素,然后切掉边界.
我只是担心这真的很慢.
所以我的问题是:
您是否知道任何快速算法(理想情况下没有任何第三方库)可以从内存中的图像/位图中删除"空"边框?
附注:算法应该"合理准确",而不是100%准确.像一条线太多或太少裁剪的一些公差将是好的.
增加1:
我刚刚以最简单的方式完成了我的强力算法.请参阅Pastebin.com上的代码.
我正在使用不安全的代码来解决Code Golf上的问题,我发现了一些我无法解释的问题.这段代码:
unsafe
{
int i = *(int*)0;
}
Run Code Online (Sandbox Code Playgroud)
与访问冲突(Segfault)崩溃,但此代码:
unsafe
{
*(int*)0=0;
}
Run Code Online (Sandbox Code Playgroud)
抛出NullReferenceException.在我看来,第一个是执行读取,第二个是执行写入.一个例外告诉我,在操作系统杀死进程之前,CLR中的某个地方正在拦截写入并停止写入.为什么这会在写入时发生,而不是在读取时发生?如果我使指针值足够大,它会在写入时发生段错误.这是否意味着CLR知道的内存块是保留的,甚至不会尝试写入?那么,为什么它允许我尝试从该块读取?我在这里完全误解了什么吗?
有趣的是:System.Runtime.InteropServices.Marshal.WriteInt32(IntPtr.Zero, 0);给我一个访问冲突,而不是NullReference.
我已经做了很多研究,但现在我仍然坚持为什么我仍然会遇到这个错误.我有一个具有以下属性的结构:
struct Account
{
//private attributes
private double mBalance;
private int mAccountNumber;
private string mName;
private string mDateCreated;
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试执行以下操作:
class BankManager
{
//private attributes
private unsafe Account *mAccounts;
private unsafe bool *mAccountsAvailable;
private int mNumberAccounts;
}
Run Code Online (Sandbox Code Playgroud)
即使将我的类帐户转换为结构,对类BankManager中的属性使用"unsafe",并告诉编译器它可以使用不安全的代码(在属性 - >构建中),我仍然会收到此错误
*mAccounts
Run Code Online (Sandbox Code Playgroud)
任何想法为什么?我很确定我在结构中使用的所有类型都是合法的,可以在c#中使用指针.提前致谢!
以下结果对我没有任何意义.在执行加法或减法之前,看起来负偏移被转换为无符号.
double[] x = new double[1000];
int i = 1; // for the overflow it makes no difference if it is long, int or short
int j = -1;
unsafe
{
fixed (double* px = x)
{
double* opx = px+500; // = 0x33E64B8
//unchecked
//{
double* opx1 = opx+i; // = 0x33E64C0
double* opx2 = opx-i; // = 0x33E64B0
double* opx3 = opx+j; // = 0x33E64B0 if unchecked; throws overflow exception if checked
double* opx4 = opx-j; // = …Run Code Online (Sandbox Code Playgroud) 在mutagen中,我在代码中注入了各种突变.我想改变的一件事是模式
if let Ok(x) = y { .. }.然而,这构成了相当大的挑战,因为我无法知道其类型y- 用户可以使用一元Ok变体构建自己的枚举.我仍然可以机会性地改变它,因为我们实际上有一个Result错误类型实现的情况Default使用类似于以下简化的特征:
#![feature(specialization)]
pub trait Errorer {
fn err(self, mutate: bool) -> Self;
}
impl<X> Errorer for X {
default fn err(self, _mutate: bool) -> Self {
self
}
}
impl<T, E> Errorer for Result<T, E>
where
E: Default,
{
fn err(self, mutate: bool) -> Self {
if mutate {
Err(Default::default())
} else {
self
}
}
}
Run Code Online (Sandbox Code Playgroud)
唉,实现的错误并不多Default,所以这不太有用.即使是实现 …