Почему ценность перезаписывается?

Во-первых, извините, я знаю, что это долго, и люди могут не читать все это, но я думаю, что нужно очень подробное объяснение.

Я пытаюсь получить длинные имена файлов, работающих с файлом 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-разрядному значению без знака.

0 ответов

Другие вопросы по тегам