标签: unsafe

C#项目设置"允许不安全的代码"的实际功能是什么

我想知道C#项目设置"允许不安全代码"是否仅适用于项目本身的不安全C#代码,还是在链接本机C++ DLL时是否需要设置此选项?如何链接自身链接到本机DLL的托管DLL?这个选项在引擎盖下真正做了什么?

c# dll interop unsafe native

6
推荐指数
3
解决办法
4106
查看次数

C#巨大的2-Dim数组

我需要在C#WinForms中声明方形矩阵,连续超过20000个项目.我读到了32位的2GB .Net对象大小限制以及64位操作系统中的相同情况.所以我理解单一答案 - 使用不安全的代码或使用C++编译器构建的独立库.

对我来说问题是值得的,因为ushort [20000,20000]小于2GB但实际上我甚至无法分配700MB的内存.我的限制是650MB,我不明白为什么 - 我有32位WinXP和3GB内存.我尝试使用Marshal.AllocHGlobal(700 << 20)但它抛出OutOfMemoryException,GC.GetTotalMemory在尝试分配内存之前返回4.5MB.

我发现只有很多人说使用不安全的代码,但我找不到如何在堆中声明2-dim数组的示例(任何堆栈都不能保存如此大量的数据)以及如何使用指针处理它.它是不安全的{}括号内的纯C++代码吗?

PS.请不要问为什么我需要如此庞大的数组...但如果你想 - 我需要分析文本(例如书籍)并找到很多索引.所以答案是 - 词之间关系的矩阵

编辑:有人可以提供一个使用不安全代码中的指针处理矩阵的小例子.我知道在32位以下不可能分配更多的空间,但我花了很多时间在谷歌搜索这样的例子,发现没什么

c# pointers unsafe multidimensional-array

6
推荐指数
2
解决办法
2509
查看次数

如果数据未按给定偏移量对齐,为什么 BitConverter.ToInt32 一次读取一个字节?

很抱歉标题令人困惑,但我想不出更好的方法来解释它。

最近在浏览源码BitConverter时,发现了一段奇怪的代码:

public static unsafe int ToInt32(byte[] value, int startIndex)
{
    fixed (byte* pbyte = &value[startIndex])
    {
        if (startIndex % 4 == 0) // data is aligned 
            return *((int*)pbyte);
        else
        { 
            if (IsLittleEndian)
            {  
                return (*pbyte) | (*(pbyte + 1) << 8)  | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24); 
            } 
            else
            { 
                return (*pbyte << 24) | (*(pbyte + 1) << 16)  | (*(pbyte + 2) << 8) | (*(pbyte + 3)); …
Run Code Online (Sandbox Code Playgroud)

.net c# pointers unsafe memory-alignment

6
推荐指数
1
解决办法
282
查看次数

如何保证在线程之间实际可以安全地共享未实现Sync的类型?

我有代码创建一个RefCell然后想要将它的引用传递RefCell单个线程:

extern crate crossbeam;

use std::cell::RefCell;

fn main() {
    let val = RefCell::new(1);

    crossbeam::scope(|scope| {
        scope.spawn(|| *val.borrow());
    });
}
Run Code Online (Sandbox Code Playgroud)

在完整的代码中,我使用的是一种RefCell嵌入其中的类型(a typed_arena::Arena).我正在使用crossbeam来确保线程不会超过它所引用的引用.

这会产生错误:

error: the trait bound `std::cell::RefCell<i32>: std::marker::Sync` is not satisfied [E0277]

    scope.spawn(|| *val.borrow());
          ^~~~~
Run Code Online (Sandbox Code Playgroud)

我相信我理解为什么会发生这样的错误:RefCell不是设计为从多个线程同时调用,并且因为它使用内部可变性,所以需要单个可变借位的正常机制不会阻止多个并发操作.这甚至记录在Sync:

不属于类型Sync是那些具有"室内易变性"在非线程安全的方式,比如CellRefCellstd::cell.

这一切都很好,但在这种情况下,我知道只有一个线程能够访问RefCell.我怎样才能向编译器确​​认我理解我在做什么,我确保是这样的?当然,如果我认为这实际上是安全的是不正确的,我会非常乐意被告知原因.

unsafe thread-safety rust

6
推荐指数
2
解决办法
1138
查看次数

通过针对具有公共成员的修改后的程序集进行编译来访问私有成员的反射的替代方法

概括

我寻找一种通过反射访问私人成员的替代方法,似乎我找到了一个。
剩下的问题是:

  1. 无论环境如何,它总是有效吗?
  2. 有什么理由不使用它?

寻找替代方案的原因

使用反射或一些稍微简化它的反射工具是以编程工作和计算资源方面的开销为代价的。特别是如果您需要使用私有类型的实例,它会变得非常麻烦。
此外,您还失去了IDE 的代码完成和其他功能的优势。即使是简单的拼写错误也可能导致错误,因为您使用字符串进行反射。

替代方法

获取原始程序集并将私有/非公共成员更改为公共成员(通过 IL 编辑器、反编译器或 Cecil)。
将这个修改后的程序集添加到您的引用中,然后您就可以轻松开发,因为编译器认为您可以访问它们(对于这个版本,您可以访问它们)。
然而,如果您针对原始程序集使用已编译的程序集,则这只适用于类型,因为如果您访问其他私有成员,则会在运行时遇到访问冲突异常。
除非您启用“允许不安全代码”,否则它似乎不再关心访问修饰符。
我没有找到有关此功能的任何信息(?),但此选项和代码中相关的不安全关键字通常主要用于指针。

对我来说它有效,但我不知道这种行为在其他情况下(例如不同的操作系统和 CLR 版本)是否一致。
另外,如果还有其他原因不使用此技术。

大会宣传员

我编写了一个工具来创建程序集的副本,其中所有成员都是公共的(类型、方法、字段、属性的 getter 和 setter)。

https://github.com/CabbageCrow/AssemblyPublicizer

它使用起来很简单,在 Windows 上您甚至可以将程序集拖放到 exe 上。

潜在的工作流程

  1. 公开原始程序集(使用工具)
  2. 使用公开的程序集作为参考
  3. 开发时无需任何思考即可访问私人成员,并对此感到高兴
  4. 启用“允许不安全代码”进行编译
    请参阅https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/unsafe-compiler-option
  5. 将您自己的程序集与原始未修改的程序集一起使用,它仍然可以神奇地访问私有成员。

c# reflection unsafe private access-modifiers

6
推荐指数
0
解决办法
401
查看次数

Java可以写入/读取已释放的堆内存吗?

这让我感到惊讶,我正在玩Java Unsafe.基本上我正在测试的是

Allocate unsafe memory -> free the memory -> Write to the freed memory
Run Code Online (Sandbox Code Playgroud)

当我访问被释放的内存时,我期待看到某种分段错误错误,但令人惊讶的是,没有引发错误/异常.

我的代码是:

protected static final Unsafe UNSAFE;
static {
    try {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        UNSAFE = (Unsafe) field.get(null);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
@Test
public void test() {
    long ptr = UNSAFE.allocateMemory(1000);
    UNSAFE.freeMemory(ptr);
    UNSAFE.putOrderedLong(null, ptr, 100L);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,如果是这样,为什么我们需要freeMemory()不安全的功能?真的是什么?

java unsafe

6
推荐指数
1
解决办法
150
查看次数

ManuallyDrop <Box <T >>是否具有mem :: uninitialized定义的行为?

我有一个[ManuallyDrop<Box<T>>]懒洋洋地填充的数组.为了实现这一点,我用"初始化"数组ManuallyDrop::new(mem::uninitialized()).

只要我只调用ManuallyDrop::drop()初始化元素,这是明确定义的行为吗?

unsafe undefined-behavior rust

6
推荐指数
1
解决办法
140
查看次数

在范围内拥有不正确(大于正确)生命周期的引用是否可以?

&'a T如果'a引用值大于引用值,引用是否会立即导致 UB(未定义行为)?或者,只要不超过 type 的引用值,就可以拥有这样的引用T吗?

作为比较:mem::transmute::<u8, bool>(2)是直接 UB,即使您从未访问过返回值。如果您有一个带有 value 的引用,情况也是如此0,因为引用必须始终有效。即使您从未访问过它们。另一方面,在ptr::null()您尝试取消引用空指针之前,拥有不是问题。

考虑这个代码:

let x = '';
let r_correct: &char = &x;

{
    let r_incorrect: &'static char = unsafe { mem::transmute(r_correct) };
    println!("{}", r_incorrect);
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,有两个对x. 都活不下去了x。但这种类型r_incorrect显然是谎言,因为x不会永远活着。

这段代码是否表现出明确定义的行为?我看到三个选项:

  • (a) 此代码表现出未定义的行为。
  • (b) 此代码的行为定义明确(“安全”)。
  • (c) Rust 还没有定义关于这部分语言的规则。

unsafe lifetime rust

6
推荐指数
2
解决办法
234
查看次数

在不安全的 Rust 中存储对结构内部数据的静态引用是否合法?

我有以下数据结构(简化):

use std::collections::HashMap;
pub struct StringCache {
    // the hashmap keys point to elements stored in `storage`
    // so never outlive this datastructure. the 'static refs are never handed out
    table: HashMap<&'static str, usize>,

    storage: Vec<Box<str>>,
}
Run Code Online (Sandbox Code Playgroud)

关于此处引用的生命周期向 Rust“撒谎”是合法/定义的行为吗?对我来说,这感觉就像违反了类型系统。这个数据结构的公共API健全吗?为了完整起见,以下是完整的实现:

use std::mem::transmute;
impl StringCache {
    pub fn intern(&mut self, entry: &str) -> usize {
        if let Some(key) = self.table.get(entry) {
            return *key;
        }
        let idx = self.storage.len();
        self.storage.push(entry.to_owned().into_boxed_str());
        // we cast our refs to 'static here.
        let key = …
Run Code Online (Sandbox Code Playgroud)

unsafe lifetime language-lawyer rust

6
推荐指数
1
解决办法
395
查看次数

为什么 std::cell::Ref 不使用引用而不是 NonNull?

Rust 中的结构体std::cell::Ref定义如下:

pub struct Ref<'b, T: ?Sized + 'b> {
    // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a
    // `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
    // `NonNull` is also covariant over `T`, just like we would have with `&T`.
    value: NonNull<T>,
    borrow: BorrowRef<'b>,
}
Run Code Online (Sandbox Code Playgroud)

评论// NB(我假设 Nota bene / Nasty Bug 或其他什么?)暗示以下定义不起作用,因为这会违反noalias(它们是否意味着后端的 LLVM 属性?):

pub struct Ref2<'b, T: ?Sized …
Run Code Online (Sandbox Code Playgroud)

unsafe language-lawyer rust refcell

6
推荐指数
1
解决办法
147
查看次数