LINUX.ORG.RU

Загадочная «error: 'mutex' in namespace 'std' does not name a type»

 


0

1

Что это вообще за зверь и с чем его едят? Гугл находит только шаманства, которые помогали людям в их специфических ситуациях (например, попытку задействовать как std::mutex реализацию из библиотеки boost), и поспешные оправдания в том, что это, мол, «local issue». А что за «local issue» и почему - нигде ничего не находится.

/usr/include/c++/6.2.0/bits/std_mutex.h на месте, в /usr/include/c++/6.2.0/mutex он упомянут, и «#include <mutex>» в исходниках (кстати, эмулятора MAME) совсем не забыто. Правда, там есть проверка на версию стандарта, но компилятор вызывается с "-std=c++14" и всё равно падает:

# make
GCC 6.2.0 detected
Precompiling src/emu/emu.h...
In file included from ../../../../../src/emu/emucore.h:37:0,
                 from ../../../../../src/emu/emu.h:29:
../../../../../src/emu/emualloc.h:128:7: ошибка: <<mutex>> в пространстве имен <<std>> не именует тип
  std::mutex              m_listlock;
       ^~~~~
make[2]: *** [precompile.make:270: ../../../../linux_gcc/obj/x64/Release/emu.h.gch] Ошибка 1
make[1]: *** [Makefile:55: precompile] Ошибка 2
make: *** [makefile:1170: linux_x64] Ошибка 2

Где может быть засада?

★★★★★

Засада может быть в версии компилятора и gch

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)

Где может быть засада?

Ну начни с простого. Как например:

Может быть какой-то дефайн, который внутри mutex/mutex.h что-то выключает.

Попробуй дополнительно

#error "<mutex> included"
#include <mutex>
в emualloc.h, что бы быть 100% уверенным, что include проходит (особенно если там какие-либо хитрые проверки).

KennyMinigun ★★★★★
()
Ответ на: комментарий от andreyu

Гм.

> g++ -std=c++17 -o test test.cpp
test.cpp: В функции <<void foo()>>:
test.cpp:5:5: ошибка: <<mutex>> не является элементом <<std>>
     std::mutex m;
     ^~~
> g++ -std=c++11 -o test test.cpp
test.cpp: В функции <<void foo()>>:
test.cpp:5:5: ошибка: <<mutex>> не является элементом <<std>>
     std::mutex m;
     ^~~
> g++ -std=c++98 -o test test.cpp
In file included from /usr/include/c++/6.2.0/mutex:35:0,
                 from test.cpp:1:
/usr/include/c++/6.2.0/bits/c++0x_warning.h:32:2: ошибка: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
 #error This file requires compiler and library support \
  ^~~~~
test.cpp: В функции <<void foo()>>:
test.cpp:5:5: ошибка: <<mutex>> не является элементом <<std>>
     std::mutex m;
     ^~~
> cat test.cpp
#include <mutex>

void foo()
{
    std::mutex m;
}
Однако
> g++ -std=c++11 -o test test.cpp
> cat test.cpp
#define _GLIBCXX_HAS_GTHREADS 1
#include <mutex>

void foo()
{
    std::mutex m;
}

int main(){
        return 0;
}

saahriktu ★★★★★
() автор топика

Попробуй собрать в однопоточном режиме, под strace. Получи командную строку сборки. Попробуй воспроизвести на одном модуле.

Если не выйдет - значит дело в переменных окружения выставляемых в процессе сборки.

pon4ik ★★★★★
()

А версия стандартной библиотеки какая? Подозреваю что он хеадеры тащит из какой-то устаревшей libstdc++... А когда ты ему включаешь c++11 - то тут ему подходит. Проверь откуда он подключает заголовки (тот же mutex).

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 2)
Ответ на: комментарий от pon4ik
> g++ -std=c++17 test test.cpp -pthread
test.cpp: В функции <<void foo()>>:
test.cpp:5:5: ошибка: <<mutex>> не является элементом <<std>>
     std::mutex m;
     ^~~

Там проблема не в "-pthread". _GLIBCXX_HAS_GTHREADS, по ходу, определяется в «bits/c++config.h». Однако прописывание строчки туда совсем не помогает. А вот прописывание строчки в исходник перед включением <mutex> помогает.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Помогает/непомогает, это не гомеопатия:)

_GLIBCXX_HAS_GTHREADS это костыль, его работа свидетельствует либо о баге в компиляторе либо в окружении.

На вскидку - хидер файлы pthreads у тебя в системе установлены?

Что кстати за дистрибутив? Был ли установлен pthreads-devel при сборке gcc?

pon4ik ★★★★★
()
Ответ на: комментарий от invy

glibc 2.24.

> ls -l /usr/lib/libstdc++.so
lrwxrwxrwx 1 root root 19 сен 17 18:49 /usr/lib/libstdc++.so -> libstdc++.so.6.0.22
Просто "-std=c++11" не подходит. Нужно «#define _GLIBCXX_HAS_GTHREADS 1», причём если добавить в системный «bits/c++config.h» руками, то не помогает. Попробовал пересобрать glibc и libstdc++, в «bits/c++config.h» так и приходит
/* Define if gthreads library is available. */
/* #undef _GLIBCXX_HAS_GTHREADS */
> find /usr/lib/ -iname 'libgthreads*'
> find /lib/ -iname 'libgthreads*'
>

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от saahriktu

если добавить в системный «bits/c++config.h», то не помогает.
вот прописывание строчки в исходник перед включением

Эм, я на всякий случай - у компиля есть опция -D.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Так можно и в исходник прописать. Но, это не меняет того, что эта опция должна читаться из файла «bits/c++config.h». И там оно таки выключено.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

впиши ошибку в этот (тот который ты думаешь что включается) файл.

А ещё лучше, посмотри на сорец после препроцессора.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Это не костыль, а опция. При сборке GCC и libstdc++ опции пишутся в «bits/c++config.h». Дистрибутив - LFS. Всё собрано как положено.

> ls -i /lib/libpthread*
804251 /lib/libpthread-2.24.so  809250 /lib/libpthread.so.0
> ls -l /usr/include/pthread.h
-rw-r--r-- 1 root root 41225 окт  3 23:09 /usr/include/pthread.h

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Это не костыль, а опция.

Это опция не для end user'ов. А использование её в явном виде это костыль.

Хз насчёт как положенно - у меня g++ на патч версию старше - и умвр :)

Попробуй gcc 6.2.1 собрать, может действительно бага была. Но, я почти уверен, что где то у тебя окружение сломанно. Может конфиг какой при сборке gcc был пропущен.

Почитай всё таки выхлоп препроцессора, может что-то сразу станет ясно.

В первую очередь я бы попробовал 6.2.1 т.к. это тупая, механическая работа которую довольно быстро провернуть.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Что толку на всё это смотреть? После препроцессора тонны разных «struct __pthread_mutex_s», «extern int pthread_mutex_init (pthread_mutex_t *__mutex,»,... и т.д., но сути это не меняет - в namespace std никакие mutex'ы не приходят. Потому, что так написано в «bits/c++config.h».

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

ls -l /usr/lib/libstdc++.so

Я про хеадеры спрашивал. На данном этапе сборки шаред либы не используются вообще.

Например у меня в системе есть:

% ls /usr/include/c++/5/mutex 
/usr/include/c++/5/mutex
% ls /usr/include/c++/4.8/mutex
/usr/include/c++/4.8/mutex

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 2)
Ответ на: комментарий от saahriktu

Ну, там ещё в комментах пишутся файлы откуда это всё берётся, как минимум.

pon4ik ★★★★★
()
Ответ на: комментарий от invy

Ты чукча не умничай, ты команду дай :D

for d in $(sudo find /usr/ -path '*include/c++' -exec echo {} \;);\
 do find $d -name 'mutex' -exec echo {} \; | \
sed "s|.*c++/\([^/]*\).*|\1|g"; \
done | sort | uniq

Ведь:

Дистрибутив - LFS

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik
# for d in $(find /usr/ -path '*include/c++' -exec echo {} \;); do find $d -name 'mutex' -exec echo {} \; | sed "s|.*c++/\([^/]*\).*|\1|g"; done | sort | uniq
6.2.0
# ls /usr/include/c++/
6.2.0
#

Всё устанавливалось и обновлялось правильно.

Тут надо понять о какой «gthreads library» идёт речь в комментариях. Может, действительно, либо надо собирать со специфическими опциями, либо должна быть задействована ещё какая-то дополнительная библиотека. По названию оно похоже на «libgthread-2.0.so» (из glib), но это как-то подозрительно. А больше нагуглить с одного захода не так-то и просто...

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от saahriktu

По названию оно похоже на «libgthread-2.0.so» (из glib), но это как-то подозрительно.

Так дело до линкера не доходит. Попробуйте 6.2.1 собрать.

andreyu ★★★★★
()

gthreads (не путать с gthread) - это библиотека абстракции от потоков из состава libgcc, используется реализацией std::mutex из libstdc++.

Если символ _GLIBCXX_HAS_GTHREADS в bits-ах libstdc++ не определен, то libgcc была собрана без поддержки потоков. Определять ее в приложении бессмысленно - слинкуется с пустой реализацией в libgcc, в которой lock/unlock ничего не делают, и мьютексы не будут ничего мьютексить.

Скорее всего, GCC был собран неправильно: наличие потоков определяется опцией --enable-threads. --enable-threads=single или no выбирают однопоточную модель (которая выбрана у вас), --enable-threads=posix выбирает pthreads. Отсутствие опции выбирает автоопределение. Автоопределение выберет posix, если сможет найти pthreads.h, или молча выберет single, если не найдет.

Рекомендую попробовать пересобрать GCC с явной опцией --enable-threads=posix. Он выдаст ошибку в процессе сборки, если не найдет pthreads, и тогда уже можно будет разбираться.

Как правило, такое бывает, когда перед сборкой GCC в sysroot (или корень, если это не кросс) были установлены не все заголовки от libc. Вполне может быть, что сейчас все заголовки на месте, сборка пройдет с ключом и с новым компилятором все заработает.

anonymous
()
Ответ на: комментарий от saahriktu

Всё собрано как положено.

LFS по книжке

Не знаю, не знаю...

anonymous
()
Ответ на: комментарий от anonymous

наличие потоков определяется опцией --enable-threads.
Не знаю, не знаю...

По книжке положено так:

SED=sed                               \
../configure --prefix=/usr            \
             --enable-languages=c,c++ \
             --disable-multilib       \
             --disable-bootstrap      \
             --with-system-zlib
Т.е. этот момент авторы таки не учли.

--enable-threads=posix

OK, попробую.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от andreyu

Не знаю где люди берут 6.2.1, на официальном сайте и зеркалах только 6.2.0. Добавил патчей gcc-6.2.0-patches-1.1.tar.bz2 из репозитория Генты. Собирается как 6.2.0.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Пересобрал с "--enable-threads=posix". Всё собралось без ошибок, и GCC, и libstdc++. Ситуация осталась прежней.

> gcc -help -v 2>&1 | grep многопоточн
Модель многопоточности: posix
> gcc -o test test.cpp
test.cpp: В функции <<void foo()>>:
test.cpp:5:5: ошибка: <<mutex>> не является элементом <<std>>
     std::mutex m;
     ^~~

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 2)
Ответ на: комментарий от saahriktu

Я конечно не уверен, т.к. мой gcc собран не мной, но смею предположить что делается это примерно так:

svn checkout svn://gcc.gnu.org/svn/gcc/trunk
pon4ik ★★★★★
()
Ответ на: комментарий от KennyMinigun

Лучше просто посмотреть результат препроцессинга, откуда что берется, заодно и ошибка может найтись

annulen ★★★★★
()
Ответ на: комментарий от pon4ik

development версии всегда бажные. Если уж так, то можно собрать сразу gcc-7-20161002, чего уж мелочиться.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Ну trunk это не совсем development версия. Хотя это зависит от процесса разработки, с коим в случае gcc я не знаком.

pon4ik ★★★★★
()
Ответ на: комментарий от saahriktu

Посмотри в сорцах системы сборки на основе чего выставляется _GLIBCXX_HAS_GTHREADS.

Ибо диф с компилирующейся версией показывает что включения мьютекса контролируется только этим флагом.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik

Гм. Разбирая исходники вперемешку с уже собранными бинарниками и другими файлами GCC нашёл файл «build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h», где всё было включено. Скопировал его руками:

# cp build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h /usr/include/c++/6.2.0/bits/
Всё заработало:
> gcc -std=c++11 -o test test.cpp
> cat test.cpp
#include <mutex>

void foo()
{
    std::mutex m;
}

int main(){
        return 0;
}
>

В сборке pilfs, кстати, такой проблемы не было и нет. В т.ч. и с GCC 6.2.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Пришлось ещё добавить

cp build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so* /usr/lib/
Теперь точно работает:
> g++ -o test3 test3.cpp -pthread
> ./test3
thread #2
thread #1
thread #8
thread #4
thread #5
thread #7
thread #6
thread #3
thread #9
thread #10
> cat test3.cpp
// mutex::lock/unlock
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex

std::mutex mtx;           // mutex for critical section

void print_thread_id (int id) {
  // critical section (exclusive access to std::cout signaled by locking mtx):
  mtx.lock();
  std::cout << "thread #" << id << '\n';
  mtx.unlock();
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_thread_id,i+1);

  for (auto& th : threads) th.join();

  return 0;
}

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от pon4ik
> time ./test4
  00   -1  -2  -3  -4  -5  -6  -7  -8  -9  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  30  31  32  33  34  35  36  37  38  39  20  21  22  23  24  25  26  27  40  41  42  43  44  45  46  47  48  49  28  29
real    0m0,003s
user    0m0,001s
sys     0m0,002s
> time ./test4
^C

real    0m16,681s
user    0m0,001s
sys     0m0,002s
> cat test4.cpp
#include <iostream>
#include <thread>
#include <mutex>

using namespace std;
const int SIZE = 10;

mutex myMutex, myMutex1, myMutex2;

void shared_cout_thread_even(int i)
{
    lock_guard<mutex> g1(myMutex1);
    lock_guard<mutex> g2(myMutex2);
    cout << " " << i << " ";
}

void shared_cout_thread_odd(int i)
{
    lock_guard<mutex> g2(myMutex2);
    lock_guard<mutex> g1(myMutex1);
    cout << " " << i << " ";
}

void shared_cout_main(int i)
{
    lock_guard<mutex> g(myMutex);
    cout << " " << i << " ";
}

void f(int n)
{
    for(int i = SIZE*(n-1); i < SIZE*n ; i++) {
        if(n % 2 == 0)
            shared_cout_thread_even(i);
        else
            shared_cout_thread_odd(i);
    }
}

int main()
{
    thread t1(f, 1);  // 0-9
    thread t2(f, 2);  // 10-19
    thread t3(f, 3);  // 20-29
    thread t4(f, 4);  // 30-39
    thread t5(f, 5);  // 40-49

    for(int i = 0; i > -SIZE; i--)
        shared_cout_main(i);  // (0, -49)

    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();

    return 0;
}
saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Ну, похоже что оно работает, хм. А либу ты тоже ведь руками копировал.

Очень странно. Можно, видимо, даже багу завести. Только по хорошему для этого нужен «чистый» lfs, что довольно таки невероятно.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Да, но теперь через всё работает и через «make install». И я, кажется, понял как всё было. Ошибкой было думать, что libstdc++ не собирается и не устанавливается вместе с GCC (а в начале книги отдельным пунктом описана сборка и установка конкретно libstdc++ во временную систему (а в прежние времена она ещё и существовала отдельно от GCC)). Получается, я дополнительными лишними шагами некорректно пересобирал её поверх правильной сборки, устанавливал эту версию вообще без std::mutex и std::thread в систему, а основные скрипты поверх этого спотыкались. Но, стоило только опять правильно собрать поверх, как всё работает и через скрипты.

В общем, по ходу, в этом и заключается «local issue» ошибки.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 2)
Ответ на: комментарий от pon4ik

Пометил. Но, время редактирования стартового поста, по ходу, истекло.

saahriktu ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.