When I was testing my application, it crashed. And after debugging it took me to this piece of code:
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;
}
and it seems to crash at:
if (StorageWriteFile((SolFSHandle)params[1],amx_Align32(&v),max*sizeof(cell),&g_amount_read)!=1)
exactly at the second parameter:
amx_Align32(&v),
with a 0x0 0x5 0x0 access voilation exception
The code of the amx_Align32 stuff is external so I don’t have access to the source of it, but in my source it looks like this:
#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];
}
with this as the export stuff:
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,
};
So, how can I align the data in the cell?
Or maybe I don’t need to align the data?
The original code was this:
if (fwrite(aligncell(&v),sizeof(cell),1,(FILE*)params[1])!=1)
I’m converting it to use with SolFS.
My guess would be that the temporary cell you create is not aligned, and you’re going off the end of it when you call
amx_Align32:So that error probably happens when you try to read it (during
StorageWriteFile). But the other problem here is that you have already written the data to potentially non-aligned memory. You need to align your memory before you write data to it.Without relying on compiler alignment pragmas etc, what you can do is this:
Now you have an aligned pointer to a
ucelland you shouldn’t need to callamx_Align32. Instead of the pointer arithmetic, you could probably substitute a call toamx_Align32:Now you can put the data in as usual (I assume the type
ucellis compatible with thecelltypes you’re putting in it):Oh, and now that I got all the way to here, I notice that your call to
StorageWriteFileis wrong. Look at how many bytes you’re writing each time around the loop:max*sizeof(cell)– that surely can’t be what you intended.Regardless of that paragraph above, everything I’ve said is still relevant. If you want to use memory alignment correctly, you need to obtain the aligned pointer first and then write the data in the correct location. Also, watch out for running off the end of your buffers.