web-dev-qa-db-ja.com

ポインターと固定サイズのバッファーは、安全でないコンテキストでのみ使用できます

私はクラス内に2つの関数があり、ParseBits()関数の呼び出しでエラーが発生します。つまり、「int num_elements = ParseBits(bits, 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;
}

機能2:

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;
        }

強調表示された行でこの関数の2つのエラーが発生します。

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
11
user1277070

おそらく私はそれを逃したかもしれませんが、あなたは実際に_int*_の使用を必要とすることを何もしていないようです。単純にint配列を渡して、ParseBits関数のシグネチャを次のように変更しないでください。

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

_unsafe{ ... }_ブロックを完全に削除します。

6
Iridium

unsafeブロックで生のポインターを使用して関数を囲む必要があります。

unsafe 
{
 //your code
}
23
Tony The Lion

私も同じ問題を抱えていましたが、ここまでの他の回答では解決できませんでした。さまざまなエラーが発生し続けました。

安全でないコードを使用する関数は、「安全でない」キーワードで宣言する必要があります。
例えば:

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/en-us/library/aa288474(v = vs.71).aspx

それはおそらく一読の価値があります、私はそれが非常に便利であるとわかりました。

6
MD-7