首先,对不起,我知道这很长,人们可能不会阅读所有内容,但我认为需要非常详细的解释。
我试图在带有FreeRTOS的Cortex M4上使用Chan Fat文件获取长文件名。我有一个奇怪的事情,由于某种原因,指针被一段看似无关的代码覆盖。你期待堆栈溢出(哈哈!),但我的堆栈很大,我尝试从我第一次遇到这个问题时进一步增加它,我真的不认为它可以是的。
我有这段代码:
uint16_t w, *lfn;
lfn = dj->lfn;
*tp = fno->lfname;
while ((w = *lfn++) != 0)
{ /* Get an LFN char */
if (i >= fno->lfsize - 1)
{
i = 0;
break;
} /* Buffer overflow, no LFN */
tp[i] = (TCHAR)w;
i++;
}
lfn
是指向16位值的指针。 w
是一个16位值。
汇编程序中的行tp[i] = (TCHAR)w;
如下:
6A7B ldr r3, [r7, #0x24]
005B lsls r3, r3, #1
68FA ldr r2, [r7, #12]
4413 add r3, r2
897A ldrh r2, [r7, #10]
801A strh r2, [r3]
通过循环的前几次一切都很好。正如您所期望的那样,lfn
在跳跃为2时从0x20009c68递增。但是,当lfn
到达0x20009c72并且代码到达行tp[i] = (TCHAR)w;
时,它会变得混乱。
前两行汇编程序取i
的值,将其左移一,得到正确的偏移量。
接下来的两行将tp
的地址放入r2
,然后添加r3
的内容,这又是必需的偏移量。
ldrh r2, [r7, #10] then puts w in r2
最后,
strh r2, [r3]
将w存储到r3
指向的位置,这是tp
指向的必要位置。
当lfn
到达0x20009c72时,汇编程序的最后一行将0x20000061放入lfn
。这是导致真正问题的一条线。在此之前,它正确地将r2
w
存储到r3
指向的位置。此时r3
包含0x20009c48,r2
包含0x00000061。但是,与以前不同,这会破坏lfn
,并将0x20000061放入其中。它显然正在影响lfn
本身。
在整段执行这段代码时,堆栈指针本身不会改变。
我想知道lfn
中dj->lfn
是指向uint16_t
而不是有限大小数组的指针是否是一个显着点? dj
是DIR类型的结构,定义如下:
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
} DIR;
WCHAR等于无符号的16位值。