Почему ценность перезаписывается?
Во-первых, извините, я знаю, что это долго, и люди могут не читать все это, но я думаю, что нужно очень подробное объяснение.
Я пытаюсь получить длинные имена файлов, работающих с файлом Chan Fat на Cortex M4 с FreeRTOS. У меня происходит странная вещь, когда по какой-то причине указатель перезаписывается, казалось бы, неподключенным фрагментом кода. Вы ожидаете переполнения стека (ха!), Но мой стек огромен, и я попытался увеличить его с того момента, когда впервые столкнулся с этой проблемой, я действительно не думаю, что это может быть так.
У меня есть этот код:
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
с 0x20009c68 с шагом 2, как и следовало ожидать. Однако когда lfn
попадает в 0x20009c72 и код попадает в строку tp[i] = (TCHAR)w;
это выходит из строя
Первые две строки ассемблера принимают значение i
сдвиньте его влево на единицу, чтобы получить правильное смещение.
Следующие две строки ставят tp
адрес в r2
, затем добавляет содержимое r3
, что, опять же, это необходимое смещение.
ldrh r2, [r7, #10] then puts w in r2
В заключение,
strh r2, [r3]
магазины в где 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-разрядному значению без знака.