0

アプリケーションをテストしているときに、クラッシュしました。そして、デバッグした後、次のコードにたどり着きました。

static cell AMX_NATIVE_CALL n_fblockwrite(AMX *amx, cell *params)
{
    cell *cptr;
    cell count;

    amx_GetAddr(amx,params[2],&cptr);

    if (cptr!=NULL)
    {
        cell max=params[3];
        ucell v;

        for (count=0; count<max; count++)
        {
            v=(ucell)*cptr++;
            if (StorageWriteFile((SolFSHandle)params[1],amx_Align32(&v),max*sizeof(cell),&g_amount_read)!=1)
            {
                break;/* write error */
            }
        }/* for */
    }/* if */
    return count;
}

そしてそれはでクラッシュするようです:

            if (StorageWriteFile((SolFSHandle)params[1],amx_Align32(&v),max*sizeof(cell),&g_amount_read)!=1)

正確に2番目のパラメータで:

amx_Align32(&v),

0x00x50x0アクセスボイレーション例外

amx_Align32のもののコードは外部にあるため、そのソースにアクセスできませんが、私のソースでは次のようになります。

#define NUDE _declspec(naked) 

NUDE uint32_t * AMXAPI amx_Align32(uint32_t *v)
{
    _asm mov eax, pAMXFunctions;
    _asm jmp dword ptr [eax+PLUGIN_AMX_EXPORT_Align32*4];
}

これをエクスポートとして使用します。

enum PLUGIN_AMX_EXPORT
{
    PLUGIN_AMX_EXPORT_Align16       = 0,
    PLUGIN_AMX_EXPORT_Align32       = 1,
    PLUGIN_AMX_EXPORT_Align64       = 2,
    PLUGIN_AMX_EXPORT_Allot         = 3,
    PLUGIN_AMX_EXPORT_Callback      = 4,
    PLUGIN_AMX_EXPORT_Cleanup       = 5,
    PLUGIN_AMX_EXPORT_Clone         = 6,
    PLUGIN_AMX_EXPORT_Exec          = 7,
    PLUGIN_AMX_EXPORT_FindNative    = 8,
    PLUGIN_AMX_EXPORT_FindPublic    = 9,
    PLUGIN_AMX_EXPORT_FindPubVar    = 10,
    PLUGIN_AMX_EXPORT_FindTagId     = 11,
    PLUGIN_AMX_EXPORT_Flags         = 12,
    PLUGIN_AMX_EXPORT_GetAddr       = 13,
    PLUGIN_AMX_EXPORT_GetNative     = 14,
    PLUGIN_AMX_EXPORT_GetPublic     = 15,
    PLUGIN_AMX_EXPORT_GetPubVar     = 16,
    PLUGIN_AMX_EXPORT_GetString     = 17,
    PLUGIN_AMX_EXPORT_GetTag        = 18,
    PLUGIN_AMX_EXPORT_GetUserData   = 19,
    PLUGIN_AMX_EXPORT_Init          = 20,
    PLUGIN_AMX_EXPORT_InitJIT       = 21,
    PLUGIN_AMX_EXPORT_MemInfo       = 22,
    PLUGIN_AMX_EXPORT_NameLength    = 23,
    PLUGIN_AMX_EXPORT_NativeInfo    = 24,
    PLUGIN_AMX_EXPORT_NumNatives    = 25,
    PLUGIN_AMX_EXPORT_NumPublics    = 26,
    PLUGIN_AMX_EXPORT_NumPubVars    = 27,
    PLUGIN_AMX_EXPORT_NumTags       = 28,
    PLUGIN_AMX_EXPORT_Push          = 29,
    PLUGIN_AMX_EXPORT_PushArray     = 30,
    PLUGIN_AMX_EXPORT_PushString    = 31,
    PLUGIN_AMX_EXPORT_RaiseError    = 32,
    PLUGIN_AMX_EXPORT_Register      = 33,
    PLUGIN_AMX_EXPORT_Release       = 34,
    PLUGIN_AMX_EXPORT_SetCallback   = 35,
    PLUGIN_AMX_EXPORT_SetDebugHook  = 36,
    PLUGIN_AMX_EXPORT_SetString     = 37,
    PLUGIN_AMX_EXPORT_SetUserData   = 38,
    PLUGIN_AMX_EXPORT_StrLen        = 39,
    PLUGIN_AMX_EXPORT_UTF8Check     = 40,
    PLUGIN_AMX_EXPORT_UTF8Get       = 41,
    PLUGIN_AMX_EXPORT_UTF8Len       = 42,
    PLUGIN_AMX_EXPORT_UTF8Put       = 43,
};

では、どうすればセル内のデータを揃えることができますか?または、データを整列させる必要がないのでしょうか。元のコードは次のとおりです。

  if (fwrite(aligncell(&v),sizeof(cell),1,(FILE*)params[1])!=1)

SolFSで使用するために変換しています。

4

1 に答える 1

1

私の推測では、作成した一時セルは整列されておらず、次のように呼び出すと、そのセルの終わりから外れますamx_Align32

ucell v;   // Not aligned to 32-bit boundary

そのため、(の間に)読み込もうとすると、おそらくエラーが発生しますStorageWriteFile。ただし、ここでのもう1つの問題は、データが非整列の可能性のあるメモリにすでに書き込まれていることです。データを書き込む前に、メモリを調整する必要があります。

コンパイラアライメントプラグマなどに依存せずにできることは、次のとおりです。

char buffer[sizeof(ucell)+4];
ucell *pv = (ucell*) (buffer + 4 - (buffer % 4));  // Align to 32-bit

これで、へのポインタが揃い、ucellを呼び出す必要はありませんamx_Align32。ポインタ演算の代わりに、次の呼び出しに置き換えることができますamx_Align32

char buffer[sizeof(ucell)+4];
ucell *pv = (ucell*) amxAlign32( (uint32_t*)buffer );

これで、通常どおりデータを入力できます(タイプは、入力するタイプucellと互換性があるとcell思います)。

*(cell*)pv = *cptr++;

ああ、そして私がここまでたどり着いた今、あなたの呼びかけStorageWriteFileが間違っていることに気づきました。ループの周りで毎回何バイトを書いているかを見てください:max*sizeof(cell)-それは確かにあなたが意図したものではありえません。

上記の段落に関係なく、私が言ったことはすべてまだ関連しています。メモリアライメントを正しく使用する場合は、最初にアライメントされたポインタを取得してから、正しい場所にデータを書き込む必要があります。また、バッファの終わりから実行されないように注意してください。

于 2012-08-01T00:41:25.873 に答える