2

Не думал, что буду здесь когда-либо спрашивать про undefined reference, ибо джуниором себя уже не считаю, но тем не менее придётся. Убедительно прошу не ставить дубликат на известный здесь вопрос, я пытался разобраться и привёл здесь максимум информации.

Начнём с того, что у меня специфическая аппаратная платформа: NMC4. SDK скачан с сайта разработчика и установлен без проблем. При компиляции возникает ошибка линкера:

nmc-g++ main.o -mnmc4 -fexceptions "D:\lab\NMC\nmpp\lib\libnmpp-nmc4d.a" "D:\lab\NMC\hal\lib\libhal-mc12101.a" -o FixPoint /cygdrive/c/Program Files/Module/NMC-SDK/nmc4-ide/lib/gcc/nmc/4.8.3/../../../../nmc/lib/nmc4/libc.a(lib_a-timesr.o): In function `__times_r': (.text.__times_r+0xd): undefined reference to `__times'

Символ __times определён в библиотеке libc.a. Вывод nm:

         U __times_r
lib_a-systimes.o:
         U __times_r
00000000 T _times
lib_a-timesr.o:
         U __times
00000000 T __times_r

Библиотека libc.a подключается автоматически тулчейном, но при принудительном подключении её в настройках компилятора ситуация не меняется. Надо полагать, что эту библиотеку линкер видит: ведь на остальные символы из этой библиотеки он не ругается.

Библиотека libc.a существует только в релизной версии. Попытка смены конфигурации проекта с Debug на Release результатов не дала.

Попытка определения символа __times в своём коде

int __times;

также результата не дала. Я же правильно понимаю, что без модификаторов доступа символы, объявленные в c-файлах имеют публичное связывание?

Техподдержка пока молчит.

/*
 * main.cpp
 *
 *  Created on: 9    . 2021  .
 *      Author: Alouette
 */

#include "nmpp.h" #include <iostream>

#define SIZE 64

//Вот эта строка, предложенная Fat-Zer, решает проблему, но использовать её - не лучшая идея //extern "C" int _times(struct tms *buf) { return -1; }

int main() { //Если закомментировать выделение памяти, то программа компилируется. //Но запускать тогда нет смысла. //Видимо, вызов __times спрятался где-то в недрах функции nmppsMalloc_8s.

nm8s *vec1 = (nm8s*)nmppsMalloc_8s(SIZE);
nm8s *vec2 = (nm8s*)nmppsMalloc_8s(SIZE);

nm8s *result = (nm8s*)nmppsMalloc_8s(SIZE);

nmppsRandUniform_8s(vec1, SIZE);
nmppsRandUniform_8s(vec2, SIZE);

nmppsAdd_8s(vec1, vec2, result, SIZE);

for (int i = 0; i &lt; SIZE; i++)
{
    std::cout &lt;&lt; nmppsGet_8s(vec1, i) &lt;&lt; &quot;+&quot; &lt;&lt; nmppsGet_8s(vec2, i) &lt;&lt; &quot;=&quot; &lt;&lt; nmppsGet_8s(result, i) &lt;&lt; std::endl;

}

std::cout.flush();

nmppsFree(vec1);
nmppsFree(vec2);
nmppsFree(result);

return 0;

}

αλεχολυτ
  • 28,987
  • 13
  • 60
  • 119
maestro
  • 4,735
  • 1
    "привёл здесь максимум информации" - ¿а где компилируемый код? ¿Это ваш код? ¿Может сначала надо было взять и собрать какой-либо пример от вендора? А то мало ли, там надо шаманить. "Техподдержка пока молчит." - так пятницо вечер. – user7860670 Mar 26 '21 at 18:00
  • 2
    согласно выводу nm__times как раз не определён (U) – Fat-Zer Mar 26 '21 at 19:54
  • попробуй определить как extern "C" int _times(struct tms *buf) { return -1; }... количество подчёркиваний определи по вкусу... – Fat-Zer Mar 26 '21 at 20:40
  • Как обходной вариант - помогло. Правда мне непонятно, почему неопределён символ __times, а при добавлении символа _times линкер больше не ругается? Разве символ подчёркивания какой-то особенный? p.s. Сегодня получил встречный вопрос от техподдержки. Как только что-то выясним, отпишусь. – maestro Mar 27 '21 at 12:57
  • @maestro, на некоторых странных платформах, как windows или различные железки _ часто добавляется к именам символов компилятором по умолчанию (см. -fleading-underscore для gcc)... учитывая, что в выводе nm'а у тебя это так для всех (по крайней мере приведённых) символов, то логично было предположить, что это как раз такой случай... – Fat-Zer Mar 27 '21 at 14:34
  • Вообще по проблеме: судя по всему, в тулчейне под капотом у тебя newlibc, а он требует самостоятельного определения «Системных вызовов» для определённых действий (неплохой блогпост по теме). В принципе это правильное решение, но другой вопрос, что именно ты там такого делаешь, что потребовало вызова times (именно для этого нужно было привести [mcve]: это просто из-за инициализации плюсового рантайма или там что-то более специфичное) и можно ли без этого обойтись... – Fat-Zer Mar 27 '21 at 14:36
  • Хорошо, почитаю на эту тему. Пример добавил, но он, скорее всего, не поможет: вызов _times спрятан где-то в недрах используемых функций. – maestro Mar 27 '21 at 15:20
  • 1
    нуда, судя по всему, если верить репам на гитхабе, то внутри nmpps* они clock() вызывают... скорей всего это какой-то код для профайлинга... в релиз он попадать по идее не должен, но почему-то они его оставили... в общем, что с этим делать лучше у них спросить... ЗЫ: на всякий пожарный, дисклеймер: я не знаком с этой архитектурой и не так хорошо знаком с применением newlib на разнообразных архитектурах, так что все мои замечания чисто умозрительные... – Fat-Zer Mar 29 '21 at 15:56

1 Answers1

2

Как ответили представители компании производителя, то, что вызов malloc тянет за собой _times, действительно ошибка. Для исправления создан коммит. Нужно обновить библиотеку NMPP и пересобрать её.

maestro
  • 4,735