Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
常数是否固定在C#中?_C#_.net_Garbage Collection - Fatal编程技术网

常数是否固定在C#中?

常数是否固定在C#中?,c#,.net,garbage-collection,C#,.net,Garbage Collection,我在使用Borland C API的C#中工作,该API对字符串使用了大量字节指针。我一直需要将一些C#字符串作为(短寿命)字节*传递 我自然会假设const对象不会在堆上分配,而是直接存储在程序内存中,但我无法在任何文档中验证这一点 下面是我为生成指向常量字符串的指针所做的一个示例。这在测试中确实起到了预期的作用,我只是不确定它是否真的安全,或者它只是靠运气起作用 private const string pinnedStringGetWeight = "getWeight"; unsafe

我在使用Borland C API的C#中工作,该API对字符串使用了大量字节指针。我一直需要将一些C#字符串作为(短寿命)字节*传递

我自然会假设const对象不会在堆上分配,而是直接存储在程序内存中,但我无法在任何文档中验证这一点

下面是我为生成指向常量字符串的指针所做的一个示例。这在测试中确实起到了预期的作用,我只是不确定它是否真的安全,或者它只是靠运气起作用

private const string pinnedStringGetWeight = "getWeight";

unsafe public static byte* ExampleReturnWeightPtr(int serial)
{
    fixed (byte* pGetWeight = ASCIIEncoding.ASCII.GetBytes(pinnedStringGetWeight))
        return pGetWeight;
}
这个常数是真的被钉住了,还是有可能被移动


@克雷根:

以下是进口:

[DllImport("sidekick.dll", CallingConvention = CallingConvention.Winapi)]
public static extern int getValueByFunctionFromObject(int serial, int function, byte* debugCallString);
这是实际的功能。是的,它实际上需要一个静态函数指针:

 private const int FUNC_GetWeight = 0x004243D0;

 private const string pinnedStringGetWeight = "getWeight";

 unsafe public static int getWeight(int serial)
 {
     fixed (byte* pGetWeight = ASCIIEncoding.ASCII.GetBytes(pinnedStringGetWeight))
         return Core.getValueByFunctionFromObject(serial, FUNC_GetWeight, pGetWeight);
 }
下面是我在模拟API时使用的另一种方法,使用静态结构,我也希望它是固定的。我希望能找到一种简化的方法

public byte* getObjVarString(int serial, byte* varName)
{
    string varname = StringPointerUtils.GetAsciiString(varName);
    string value = MockObjVarAttachments.GetString(serial, varname);
    if (value == null)
        return null;
    return bytePtrFactory.MakePointerToTempString(value);
}

static UnsafeBytePointerFactoryStruct bytePtrFactory = new UnsafeBytePointerFactoryStruct();
private unsafe struct UnsafeBytePointerFactoryStruct
{
    fixed byte _InvalidScriptClass[255];
    fixed byte _ItemNotFound[255];
    fixed byte _MiscBuffer[255];

    public byte* InvalidScriptClass
    {
        get
        {
            fixed (byte* p = _InvalidScriptClass)
            {
                CopyNullString(p, "Failed to get script class");
                return p;
            }
        }
    }

    public byte* ItemNotFound
    {
        get
        {
            fixed (byte* p = _ItemNotFound)
            {
                CopyNullString(p, "Item not found");
                return p;
            }
        }
    }

    public byte* MakePointerToTempString(string text)
    {
        fixed (byte* p = _ItemNotFound)
        {
            CopyNullString(p, text);
            return p;
        }
    }

    private static void CopyNullString(byte* ptrDest, string text)
    {
        byte[] textBytes = ASCIIEncoding.ASCII.GetBytes(text);
        fixed (byte* p = textBytes)
        {
            int i = 0;
            while (*(p + i) != 0 && i < 254 && i < textBytes.Length)
            {
                *(ptrDest + i) = *(p + i);
                i++;
            }
            *(ptrDest + i) = 0;
        }
    }
}
public byte*getObjVarString(int-serial,byte*varName)
{
string varname=StringPointerUtils.getascistring(varname);
string value=MockObjVarAttachments.GetString(serial,varname);
如果(值==null)
返回null;
返回bytePtrFactory.MakePointerToTempString(值);
}
静态UnsafeBytePointerFactoryStruct bytePtrFactory=新UnsafeBytePointerFactoryStruct();
私有不安全结构UnsafeBytePointerFactoryStruct
{
固定字节_invalidScript类[255];
固定字节_ItemNotFound[255];
固定字节_miscsbuffer[255];
公共字节*InvalidScript类
{
得到
{
已修复(字节*p=\u InvalidScript类)
{
CopyNullString(p,“无法获取脚本类”);
返回p;
}
}
}
公共字节*ItemNotFound
{
得到
{
已修复(字节*p=\u ItemNotFound)
{
CopyNullString(p,“未找到项”);
返回p;
}
}
}
公共字节*MakePointerToTempString(字符串文本)
{
已修复(字节*p=\u ItemNotFound)
{
CopyNullString(p,text);
返回p;
}
}
私有静态void CopyNullString(字节*ptrDest,字符串文本)
{
byte[]textBytes=ascienceoding.ASCII.GetBytes(text);
固定(字节*p=textBytes)
{
int i=0;
而(*(p+i)!=0&&i<254&&i
在这种情况下,常量的分配方式应该无关紧要,因为
ascienceoding.ASCII.GetBytes()
返回一个新的字节数组(它不能返回常量的内部数组,因为它的编码不同(编辑:由于字符串是不可变的,所以希望无法获得指向
字符串的内部数组的指针)). 但是,GC不会接触数组的保证只在
固定的
作用域接触数组时有效-换句话说,当函数返回时,内存不再固定。

根据Kragans的注释,我研究了将字符串整理为字节指针的正确方法,现在我在问题中使用的第一个示例使用以下内容:

        [DllImport("sidekick.dll", CallingConvention = CallingConvention.Winapi)]
        public static extern int getValueByFunctionFromObject(int serial, int function, [MarshalAs(UnmanagedType.LPStr)]string debugCallString);

这不是将字符串封送到本机代码的方法-您可以发布一个(大概是P/Invoke)调用到C API的示例吗?我强烈怀疑常量字符串实际上是“固定”的,因为我不相信它们存储在垃圾收集堆上。这方面的一个证据是,常量字符串是使用“Ldstr”IL操作码加载的,常量字符串是作为方法体的一部分提供的。“fixed语句防止垃圾收集器重新定位可移动变量。fixed语句仅在不安全的上下文中允许使用。fixed还可用于创建固定大小的缓冲区。”———RunUO is so 2010:——)我很确定不能保证固定字符串常量(对于值类型常量,这个问题没有意义,所以我们这里只讨论字符串常量)。我认为主要的区别是,它们默认情况下会被占用,但占用并不意味着固定。只分配一些非托管内存如何?这一个肯定会被固定。这肯定回答了我的问题。完全没有回答。非常感谢。我返回的字节*一旦返回就完全不可靠,我很幸运。如果它回答了您的问题,您应该将此标记为答案。@Judah Himango:我不确定是否回答了常量是否固定的字面主题问题,即使这个答案完全足以满足关于我自己代码正确性的问题。谢谢您的编辑。一个好的观点:)如果我重新表述这个问题,我会问如何在程序集的整个过程中建立并修复指向字节[]的指针,在某种程度上,字符串的特殊性质使问题变得复杂。我现在走对了。再次感谢你的帮助。