Ошибка компилятора при приведении к указателю на функцию - PullRequest
2 голосов
/ 19 апреля 2010

Я пишу загрузчик для PIC32MX, используя компилятор HiTech's PICC32 (аналогично C90). В какой-то момент мне нужно перейти к основной процедуре real , поэтому где-то в загрузчике у меня есть

void (*user_main) (void);
user_main = (void (*) (void)) 0x9D003000;
user_main();

(Обратите внимание, что в реальном коде сигнатура функции - это typedef'd, а адрес - макрос.)

Я бы предпочел рассчитать этот (виртуальный) адрес из физического адреса и получить что-то вроде:

void (*user_main) (void);
user_main = (void (*) (void)) (0x1D003000 | 0x80000000);
user_main();

... но когда я пытаюсь это сделать, я получаю ошибку компилятора:

Error #474: ; 0: no psect specified for function variable/argument allocation

Я тут что-то сказал о неясности синтаксиса С?

Эта ошибка не относится к какой-либо конкретной строке, но если я закомментирую вызов user_main(), она исчезнет. (Это может быть компилятор, удаляющий избыточную ветвь кода, но HiTech PICC32 не особенно хорош в облегченном режиме, так что, возможно, нет.)

Обновление : я также заметил, что если я использую

void (*user_main) (void);
unsigned int x = 0x9D003000;
user_main = (void (*) (void)) x;
user_main();

Я получаю ту же ошибку.

Ответы [ 5 ]

3 голосов
/ 19 апреля 2010

Это не общая проблема C - она ​​специфична для HI-TECH.

Я никогда не использовал продукты HI-TECH, но, похоже, проблема в том, что компоновщик не знает, где в памяти он должен разместить аргументы или локальные переменные подпрограммы user_main. Из руководства PICC :

(474) не указано psect для функции переменной / распределения аргументов (компоновщик)

Директива ассемблера FNCONF, которая указывает компоновщику информацию, касающуюся блока auto / parameter, никогда не была замечена. Это предоставляется в стандартных файлах времени выполнения при необходимости. Эта ошибка может означать, что правильный модуль запуска во время выполнения не был связан. Убедитесь, что вы использовали директиву FNCONF, если модуль запуска во время выполнения написан от руки.

1 голос
/ 26 апреля 2010

Извините, что отвечаю на мой вопрос, но это была ошибка в компиляторе. Они прислали мне более свежую сборку, которая устранила проблему.

1 голос
/ 19 апреля 2010

Я понимаю, что это не ответ на первоначальный вопрос, но синтаксис вызова функции через указатель на функцию можно сделать намного более понятным (правильным) с помощью следующей конструкции:

(*user_main)();

Если вы сделаете это, вы сразу увидите, что user_main - это указатель, на который разыменовывается и выполняется вызов функции. Это позволяет избежать путаницы указателя на функцию user_main с функцией user_main ().

1 голос
/ 19 апреля 2010

Вы можете быть правы в отношении удаления избыточного кода компилятором при удалении вызова функции. GCC -S я думаю, что вы получите вывод сборки, который вы затем сможете использовать для подтверждения отсутствия определения функции после удаления сайта вызова функции.

Полагаю, это поможет вам улучшить вашу отладку ...

0 голосов
/ 19 апреля 2010

Уродливый способ сделать это может заключаться в том, чтобы поместить тип указателя и длинный без знака в объединение. Вы знаете, что вам нужно сделать. Стандарт C делает это неопределенное поведение, но вы уже находитесь на неопределенной территории и во власти вашего компилятора, как только вам нужно преобразовать целое число в указатель.

...