私は関数ポインタの配列を通ってこれらの関数を順番に呼び出す関数を持っています。配列の内容を変更しながら配列内のポインタで関数を呼び出す
このプロセス中に関数ポインタの配列の内容が変更されるとどうなりますか?関数呼び出しは、予期せぬことが起こることがないように十分にアトミックであると考えることができるか、スタック上のプッシュが行われている間に関数ポインタを変更しないよう注意しなければならないか?
下記の例(擬似)コードです。 init()は起動時に1回実行され、callFunctions()は定期的に実行されます(たとえば、1秒に1回)。次にchangeFunctions()が来て、functionPtrArray []の内容を変更します。これは、コードがOSのような環境の異なるプロセスで実行されるため、いつでも発生する可能性があります。
void (*functionPtrArray[3]) (void);
void init(void)
{
functionPtrArray[0] = function1;
functionPtrArray[1] = function2;
functionPtrArray[2] = function3;
}
void callFunctions(void)
{
for (i = 0; i < 3; i++)
{
*functionPtrArray[i]();
}
}
void changeFunctions(void)
{
functionPtrArray[0] = newFunction1;
functionPtrArray[1] = newFunction2;
functionPtrArray[2] = newFunction3;
}
重要な質問は、一度f [0]が実行されると、f [1]とf [2]はf [0]と同じ集合からのものであるかどうかです。それ以外の場合、コードは正常です(関数ポインタを取得して格納することは基本的であり、基本的にはネイティブCPUとバスワードサイズであるため、1サイクルで読み書きサイクルがネイティブマシンワード全体をフェッチ/ストアします)。 –
@PaulOgilvie何らかの汎用CPUが1サイクルで1ワード(xバイト)を読み込むことができると思いますか?たとえその前提が真実であったとしても、アーキテクチャの多くは、コードとデータの両方を格納するために使用されることを意図したマシンのワードサイズを超えたアドレスを拡張しています。 – Lundin