指针和固定大小缓冲区只能在不安全的上下文中使用。

12

我在一个类中有两个函数,调用ParseBits()函数时遇到了错误,即"int num_elements = ParseBits(bits, buffer);",因为我传递了"buffer"参数 "public int ParseBits(string bits, int* buffer)":

函数1:

public float AssignFitness(string bits, int target_value)
        {

   //holds decimal values of gene sequence
   int[] buffer = new int[(VM_Placement.AlgorithmParameters.chromo_length / VM_Placement.AlgorithmParameters.gene_length)];

   int num_elements = ParseBits(bits, buffer);

   // ok, we have a buffer filled with valid values of: operator - number - operator - number..
   // now we calculate what this represents.
   float result = 0.0f;

   for (int i=0; i < num_elements-1; i+=2)
   {
      switch (buffer[i])
      {
         case 10:

            result += buffer[i+1];
            break;

         case 11:

            result -= buffer[i+1];
            break;

         case 12:

            result *= buffer[i+1];
            break;

         case 13:

            result /= buffer[i+1];
            break;

      }//end switch

   }

   // Now we calculate the fitness. First check to see if a solution has been found
   // and assign an arbitarily high fitness score if this is so.

   if (result == (float)target_value)

      return 999.0f;

   else

      return 1/(float)fabs((double)(target_value - result));
   //   return result;
}

第二个功能:

public int ParseBits(string bits, int* buffer)
        {

            //counter for buffer position
            int cBuff = 0;

            // step through bits a gene at a time until end and store decimal values
            // of valid operators and numbers. Don't forget we are looking for operator - 
            // number - operator - number and so on... We ignore the unused genes 1111
            // and 1110

            //flag to determine if we are looking for an operator or a number
            bool bOperator = true;

            //storage for decimal value of currently tested gene
            int this_gene = 0;

            for (int i = 0; i < VM_Placement.AlgorithmParameters.chromo_length; i += VM_Placement.AlgorithmParameters.gene_length)
            {
                //convert the current gene to decimal
                this_gene = BinToDec(bits.Substring(i, VM_Placement.AlgorithmParameters.gene_length));

                //find a gene which represents an operator
                if (bOperator)
                {
                    if ((this_gene < 10) || (this_gene > 13))

                        continue;

                    else
                    {
                        bOperator = false;
                        buffer[cBuff++] = this_gene;
                        continue;
                    }
                }

                //find a gene which represents a number
                else
                {
                    if (this_gene > 9)

                        continue;

                    else
                    {
                        bOperator = true;
                        buffer[cBuff++] = this_gene;
                        continue;
                    }
                }

            }//next gene

            //   now we have to run through buffer to see if a possible divide by zero
            //   is included and delete it. (ie a '/' followed by a '0'). We take an easy
            //   way out here and just change the '/' to a '+'. This will not effect the 
            //   evolution of the solution
            for (int i = 0; i < cBuff; i++)
            {
                if ((buffer[i] == 13) && (buffer[i + 1] == 0))

                    buffer[i] = 10;
            }

            return cBuff;
        }

这个函数在高亮的行上出现了两个错误:

Error 1: The best overloaded method match for 'VM_Placement.Program.ParseBits(string, int*)' has some invalid arguments

Error 2: Pointers and fixed size buffers may only be used in an unsafe context

那么你的问题是什么呢?为什么会出现错误?你可以采取哪些措施来避免这种情况发生?为什么在托管代码中不能使用指针或其他方法?(清楚地表达你需要帮助的内容比猜测更容易帮助你,我们可能是对的,也可能不是)。 - Rune FS
我该怎么做才能避免这些错误...我猜测我在ParseBits()函数中传递参数的方式不正确,因此我得到了另一个错误"Argument 2: cannot convert from 'int[]' to 'int*'"。 - user1277070
你为什么一开始就要使用指针? - harold
3个回答

26

你需要在 unsafe 块中使用原始指针来包装您的函数。

unsafe 
{
 //your code
}

如何调用该函数?将函数设置为不安全后,"指针和固定大小缓冲区仅可在不安全的上下文中使用"错误被移除了,但我仍然在该函数调用中收到"The best overloaded method match for 'VM_Placement.Program.ParseBits(string, int*)' has some invalid arguments"的错误提示。 - user1277070
我会说你也需要将函数的调用点标记为unsafe,因为它也需要指针。 - Tony The Lion
没有,没成功……我猜是因为我传递的参数类型不对……在调用ParseBits()时,我又遇到了一个参数传递的错误:“第二个参数:无法将'int[]'转换为'int*'”。 - user1277070
2
@user1277070 在 C# 中,T[](在您的情况下为 int[])不是 T*,这就是为什么您会收到错误的原因。 - Rune FS

9

我曾经遇到同样的问题,但是这里其他答案都没有解决我的问题。我一直收到不同的错误提示。

无论使用哪个函数,只要其中包含不安全代码,就需要用“unsafe”关键字进行声明。
例如:

static unsafe void myFunction(int* myInt, float* myFloat)  
{
    // Function definition
}

就我个人而言,在创建包装类时,我试图做到这一点。
对于那些感兴趣的人,最终看起来是这样的:

using System.Runtime.InteropServices;

namespace myNamespace
{
    public class myClass
    {
        [DllImport("myLib.so", EntryPoint = "myFunction")]
        public static extern unsafe void myFunction(float* var1, float* var2);
    }
}

在 MSDN 的“不安全代码教程”中有很多有用的信息:
https://msdn.microsoft.com/zh-cn/library/aa288474(v=vs.71).aspx

这篇文章值得一读,我发现它非常有用。


4
请注意,使用unsafe声明还需要在项目属性中的“构建”选项卡下检查“允许不安全代码”选项。 - Yoav Feuerstein

6

也许我错过了什么,但您似乎并没有实际需要使用 int*。为什么不直接传递一个 int 数组,并将 ParseBits 函数签名更改为:

public int ParseBits(string bits, int[] buffer)

然后完全删除 unsafe{ ... } 块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接