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)

正好在第二个参数:

amx_Align32(&v),

带有 0x0 0x5 0x0 访问破坏异常

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),可能会发生该错误。但这里的另一个问题是您已经将数据写入可能未对齐的内存。在向内存写入数据之前,您需要对齐内存。

在不依赖编译器对齐编译指示等的情况下,您可以执行以下操作:

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

现在你有一个指向 a 的对齐指针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 回答