Страницы

Поиск по вопросам

Показаны сообщения с ярлыком gdb. Показать все сообщения
Показаны сообщения с ярлыком gdb. Показать все сообщения

воскресенье, 9 февраля 2020 г.

GDB пропускает строки кода с++

#cpp #отладка #gdb


Вот программа:

#include 

int main()
{
    try
    {
        throw std::out_of_range("Huston, we have a problem");
    }
    catch(std::out_of_range obj)
    {

    }

    std::cout << "Hello world" << std::endl;

return 0;
}


Компилирую ее с помощью команды:

g++ -g -O0 main.cpp


Запускаю в gdb и пытаюсь отладить:

(gdb) break main
Breakpoint 1 at 0x100000d42: file main.cpp, line 7.
(gdb) run
Starting program: /Users/admin/repositories/oop_workspace/a.out 
[New Thread 0x1c03 of process 5743]
warning: unhandled dyld version (15)

Thread 2 hit Breakpoint 1, main () at main.cpp:7
7           throw std::out_of_range("Huston, we have a problem");
(gdb) next
Hello world
[Inferior 1 (process 5743) exited normally]
(gdb) 
The program is not being run.


Код ниже try-catch блока не отлаживается, а вместо этого просто выполняется.
В чем может быть проблема?
    


Ответы

Ответ 1



Где-то в сети я видел сообщение, что в Linux проблема (останов по stepping после С++ exception) решена, но не нашлось никого, кто перенес бы этот fix в MinGW :). Однако, оказалось что в моей Linux avp-ubu1 4.4.0-127-generic #153-Ubuntu SMP Sat May 19 10:58:46 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux, также как у вас, не работает. Остается воспользоваться советом из Debugging with GDB и ввести команду catch catch перед запуском. Вот результат: avp@avp-ubu1:hashcode$ g++ t.cpp -g avp@avp-ubu1:hashcode$ gdb ./a.out GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./a.out...done. (gdb) catch catch Catchpoint 1 (catch) (gdb) r Starting program: /home/avp/hashcode/a.out Catchpoint 1 (exception caught), 0x00007ffff7ae1711 in __cxa_begin_catch () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (gdb) n Single stepping until exit from function __cxa_begin_catch, which has no line number information. main () at t.cpp:14 14 std::cout << "Hello world" << std::endl; (gdb) Hello world 16 return 0; (gdb) 17 } (gdb) c Continuing. [Inferior 1 (process 11769) exited normally] (gdb) q avp@avp-ubu1:hashcode$ Как видите, все получилось. Если остановиться в начале (br main) и идти построчно (next), то тоже все нормально работает. P.S. Для останова в точке генерации exception введите команду catch throw.

среда, 5 февраля 2020 г.

Отладка с помощью gdbserver

#cpp #gdb


Иногда возникает необходимость удаленной отладки и сдесь не обойтись без gdbserver,
но есть одна проблема: исходники. Чтобы gdb видел исходники, нужно чтобы они лежали
по тому же пути, что и на машине, где запущен gdbserver, что может доставить проблем
(когда например домашняя директория отличается). Можно ли решить эту проблему кроме
как созданием нового пути, который будет идентичен на обеих машинах?

PS Связанный вопрос: можно ли удаленно дебажить с помощью gdbserver программу в windows
на линуксе? У меня при попытке приконнектится (компилятор на линуксе gcc, на windows
mingw аналогичных версий) вылетает ошибка о несовместимости.
    


Ответы

Ответ 1



Исходная ситуация Определённости ради ситуация такова: * файл изначально собран на удалённой машине * исходники лежали в /server/src/path * из них собран файл /server/bin/myapp * файл собран cmake'ом или чем-то подобным и компилятору передавались полные пути * отладочную информацию собрать не забыли (ключик -g или -ggdb) * на локальной машине точно такое же дерево исходников лежит в /home/user/src/path Запускаем: r$ gdbserver 192.168.0.16:5555 /server/bin/myapp Подключаемся: (gdb) target remote 192.168.0.16:5555`
И видим: Remote debugging using 192.168.0.16:5555 warning: No executable has been specified and target does not support determining executable automatically. Try using the "file" command. warning: Could not load vsyscall page because no executable was specified 0xb7fdf1d0 in ?? () Команды вроде b main не работают, а в bt только бессмысленные адреса и вопросы, будто мы отлаживаем strip'нутый бинарник. Загрузка символов Дабы gdb мог подгрузить символы, нужно иметь точно такой же собранный файл отлаживаемой программы (или хотя бы его отладочные символы) на локальной машине. Так что копируем его: l$ scp 192.168.0.16:/server/bin/myapp /tmp/myapp или с помощью самого gdb: (gdb) remote get /server/bin/myapp /tmp/myapp Затем загружаем файл: (gdb) file /tmp/myapp И заново запускаем gdbserver/подключаемся и видим, что ситуация улучшилась: (gdb) b main Breakpoint 1 at 0x804840d: file /server/src/path/myapp.c, line 4. (gdb) c Continuing. Reading /lib/i386-linux-gnu/libc.so.6 from remote target... Reading /lib/i386-linux-gnu/libc-2.15.so from remote target... Reading /lib/i386-linux-gnu/.debug/libc-2.15.so from remote target... Breakpoint 1, main () at /server/src/path/myapp.c:4 4 /server/src/path/myapp.c: Нет такого файла или каталога. (gdb) bt #0 main () at /home/alexander/tmp/foo.c:4 list, step и next по прежнему не работают ввиду того, что исходники отличаются. Коррекция положения исходных кодов. Т.к. уже условились, что копия дерева исходников лежит в /home/user/src/path, следующей команды должно быть достаточно: (gdb) set substitute-path /server/foo/path /home/user/src/path После этого всё ожидаемое должно работать: (gdb) l 1 #include 2 3 int main() { 4 getc(stdin); 5 return 0; 6 } Другие возможности по заданию расположения исходников Если, например, локально исходники лежат в /local/path/server/foo/path, то можно обойтись: directory /local/path или если все *.cpp лежат в одной папке/нужен конкретный файл, то в directory можно указать путь только к ним: directory ` /local/path/src` Подробности в Debugging with GDB

пятница, 31 января 2020 г.

gdb отладка многопоточного приложения

#cpp #linux #c #gdb


здравствуйте, возникла необходимость научиться отлаживать многопоточное приложение
через gdb... предположим, есть такое приложение с несколькими потоками:

int main() {
     static int i =0;
     std::thread([](){ while(true) { ++i; std::this_thread::sleep_for( std::chrono::milliseconds(700));
std::cout << "hello\n";}}).detach();
     std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(600));
std::cout << "my\n";}}).detach();
     std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(900));
std::cout << "world\n";}}).detach();
     std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(700));
std::cout << "ro\n";}}).join();
}


подключаемся gdb -p number_of_pid процесс: 

Type "apropos word" to search for commands related to "word".
Attaching to process 9208
[New LWP 9209]
[New LWP 9210]
[New LWP 9211]
[New LWP 9212]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x00007f1bae990acd in pthread_join () from /lib64/libpthread.so.0


и приложение останавливается... подскажите как увидеть в отладчике значение переменной
i, если как только присоединяемся gdb, то все останавливается, а если делаем next,
потом, предположим, br в какой-то строке, затем далее n, то все идет по-прежнему, значение
переменной i(через print) вывести не удается...
    


Ответы

Ответ 1



Базовые заметки молодой хозяйке Для отладки (по крайней мере для комфортной отладки) необходимо собирать с отладочной информацией, в gcc для этого используется ключ -g: g++ -pthread -g thr.cpp -o thr Можно либо сразу запустить процесс под gdb: gdb ./thr либо привязаться к уже запущенному процессу: gdb -p В первом случае, после запуска отладчика собственно процесс нужно запустить коммандой run или r (gdb) r Starting program: /tmp/thr [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". [New Thread 0x7ffff6ee0700 (LWP 27964)] [New Thread 0x7ffff66df700 (LWP 27965)] [New Thread 0x7ffff5ede700 (LWP 27966)] [New Thread 0x7ffff56dd700 (LWP 27967)] my hello ro world ....... Процесс можно в любой момент приостановить SIGINT'ом или, другими словами, Ctrl+C. Определение обстановки После остановки в произвольной точке стоит посмотреть, где же мы находимся, для этого есть команды backtrace (b) и info threads (i th) Thread 1 "thr" received signal SIGINT, Interrupt. 0x00007ffff729a93d in pthread_join () from /lib64/libpthread.so.0 (gdb) bt #0 0x00007ffff729a93d in pthread_join () from /lib64/libpthread.so.0 #1 0x00007ffff7ab7537 in std::thread::join() () from /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/libstdc++.so.6 #2 0x0000555555555310 in main () at thr.cpp:13 (gdb) i th Id Target Id Frame * 1 Thread 0x7ffff7f7d740 (LWP 28093) "thr" 0x00007ffff729a93d in pthread_join () from /lib64/libpthread.so.0 2 Thread 0x7ffff6ee0700 (LWP 28097) "thr" 0x00007ffff72a4e4d in nanosleep () from /lib64/libpthread.so.0 3 Thread 0x7ffff66df700 (LWP 28098) "thr" 0x00007ffff72a4e4d in nanosleep () from /lib64/libpthread.so.0 4 Thread 0x7ffff5ede700 (LWP 28099) "thr" 0x00007ffff72a4e4d in nanosleep () from /lib64/libpthread.so.0 5 Thread 0x7ffff56dd700 (LWP 28100) "thr" 0x00007ffff72a4e4d in nanosleep () from /lib64/libpthread.so.0 Как видно, gdb сейчас находится в контексте pthread_join() основного потока. Смена кадра стека и печать переменной Чтобы распечатать переменную (print) нужно переключиться на кадр, в котором она находится для этого есть команда frame (f), заодно можно посмотреть листинг(list): (gdb) f 2 #2 0x0000555555555310 in main () at thr.cpp:13 13 std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(700)); std::cout << "ro\n";}}).join(); (gdb) l 8 std::this_thread::sleep_for( std::chrono::milliseconds(700)); 9 std::cout << "hello\n";} 10 }).detach(); 11 std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(600)); std::cout << "my\n";}}).detach(); 12 std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(900)); std::cout << "world\n";}}).detach(); 13 std::thread([](){ while(true) { std::this_thread::sleep_for(std::chrono::milliseconds(700)); std::cout << "ro\n";}}).join(); 14 } (gdb) p i $1 = 3 где двойка в frame 2 — это номер интересующего кадра в выводе bt. Пошаговая отладка потока Чтобы по-шагам отлаживать конкретный поток нужно переключить gdb в его контекст командой thread (thr): (gdb) thread 2 [Switching to thread 2 (Thread 0x7ffff6ee0700 (LWP 28097))] #0 0x00007ffff72a4e4d in nanosleep () from /lib64/libpthread.so.0 У каждого потока свой стек, поэтому не лишним будет снова посмотреть backtrace и, по необходимости, перейти в нужный кадр. (gdb) bt #0 0x00007ffff72a4e4d in nanosleep () from /lib64/libpthread.so.0 #1 0x0000555555556aa7 in std::this_thread::sleep_for > (__rtime=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/include/g++-v6/thread:323 #2 0x0000555555555140 in ::operator()(void) const (__closure=0x55555576bc28) at thr.cpp:8 #3 0x0000555555556524 in std::_Bind_simple()>::_M_invoke<>(std::_Index_tuple<>) (this=0x55555576bc28) at /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/include/g++-v6/functional:1391 #4 0x0000555555556394 in std::_Bind_simple()>::operator()(void) (this=0x55555576bc28) at /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/include/g++-v6/functional:1380 #5 0x0000555555556292 in std::thread::_State_impl()> >::_M_run(void) (this=0x55555576bc20) at /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/include/g++-v6/thread:197 #6 0x00007ffff7ab724e in ?? () from /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/libstdc++.so.6 #7 0x00007ffff7299657 in start_thread () from /lib64/libpthread.so.0 #8 0x00007ffff6fd9c5f in clone () from /lib64/libc.so.6 После этого можно отлаживать поток привычным способом с помощью next/step (n/s): (gdb) n Single stepping until exit from function nanosleep, which has no line number information. my world ro std::this_thread::sleep_for > (__rtime=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/include/g++-v6/thread:328 328 } (gdb) my world ro ::operator()(void) const (__closure=0x55555576bc28) at thr.cpp:9 9 std::cout << "hello\n";} (gdb) my ro world hello 7 ++i; (gdb) my world ro 8 std::this_thread::sleep_for( std::chrono::milliseconds(700)); (gdb) world my ro my ro 9 std::cout << "hello\n";} (gdb) my world ro hello 7 ++i; (gdb) my world ro 8 std::this_thread::sleep_for( std::chrono::milliseconds(700)); (gdb) p i $2 = 5 Стоит упомянуть пару замечаний: Ради пошаговый отладки код был слегка переформатирован, как видно в листинге выше. Касательно многопоточных приложений: при возврате управления процессу по n запускаются сразу все потоки, поэтому можно видеть дополнительный вывод почти после каждой комманды. К последующему прочтению/просмотру рекомендую, как минимум, букварь «Отладка с помощью GDB»

суббота, 4 января 2020 г.

Как размещаются стековые переменные в C

#c #gdb #x64


Здравствуйте. Я копаюсь с помощью отладчика в коде, и пытаюсь понять по какому принципу
GCC (C-compiler) размещает переменные (локальные) в стеке. Сначала я думал что он проталкивает
их в том же порядке:



то есть встретил int auth_flag и толкает в стек, переменная соответственно получает
больший адрес (т.к. стек растёт в направлении младших адресов). Потом password_buffer
уже получает адрес меньше. Но когда я поменял их местами -- ничего не изменилось:



auth_flag по прежнему получает адрес больше и (т.е. стоит ниже в стеке чем password_buffer).
Я бы подумал что так и должно быть, но этот пример взял с книги, и там, когда автор
меняет местами переменные, -- они меняются местами и в стеке. Книга за 2010 год, x32
архитектура, возможно GCC моложе. 

Поясните почему так происходит, почему компилятор не даёт самому выбирать порядок
размещения переменных и чем он "руководствуется" когда размещает переменные. 

GCC version: 4.9.2
    


Ответы

Ответ 1



Посмотрите на это с другой стороны. Если компилятор поменяет местами эти две переменные в стеке, это повлияет как-то на Ваш код? ответ - скорее всего Вы даже не узнаете об этом. А раз так, значит компилятор может расставить в стеке переменные так, как ему кажется правильным. И эти правила порой такие сложные, что только разработчики компилятора и процессора могут их аргументировать. Но есть случаи, когда компилятор может переставить ещё хитрее. Например, в так называемом RVO. Если в функции создается объект и он из нее возвращается, то компилятор может это увидеть и создать объект ещё в стеке вызывающей функции. Таким образом, экономится вызов конструктора копирования и деструктора. Но вернемся к вопросу, почему компилятор все-таки переставляет переменные? Он может ставить переменные так, что бы они были выровнены по границе в 16 байт - таким образом получится ускорение.

пятница, 3 января 2020 г.

Роль организации GNU

#cpp #unix #gdb #gnu


Не могу понять роль организации GNU. Переводится как некий проект ***not Unix. Эм...ну
если not Unix, то почему тогда их проект gdb это отладчик под Unix системы?
    


Ответы

Ответ 1



Проект GNU (англ. The GNU Project) — проект по разработке свободного программного обеспечения (СПО), является результатом сотрудничества множества отдельных проектов. Проект был запущен программистом и сторонником СПО Ричардом Столлманом 27 сентября 1983 года в Массачусетском технологическом институте. Изначальной целью проекта было «разработать достаточно свободного программного обеспечения, чтобы можно было обойтись без программного обеспечения, которое не является свободным». Текущая работа проекта GNU включает в себя разработку программного обеспечения, повышение осведомлённости, проведение политических кампаний и раздачу новых материалов. Пожалуй, в контексте твоего вопроса, интереснее всего фраза является результатом сотрудничества множества отдельных проектов Манифест Лицензии Программы. Уверен, тебя заинтересует список. Философию происходящего в этом проекте хорошо иллюстрирует существование нежно мною любимой LibreJS. дополнение к Firefox, позволяющее отказаться от выполнения несвободного JavaScript-кода. По мнению Ричарда Столлмана, проблема с JavaScript состоит в том, что код загружается без ведома пользователя, не давая возможности оценить степень его свободности перед загрузкой и воспрепятствовать выполнению проприетарного JavaScript-кода. Определение применяемой в JavaScript-коде лицензии производится через указание на сайте специальных меток или через анализ наличия упоминания лицензии в комментариях к коду. Кроме того, по умолчанию допускается выполнение тривиального JavaScript-кода, известных библиотек и кода с сайтов, занесённых пользователем в белый список.

Ответ 2



Про название. В старом *nix-мире обычной практикой было, что кто-то брал какую-то программу, немного изменял её или писал совместимую, но немного отличающуюся. В итоге новую программу нужно как-то было называть. Обычно или добавлялось пару букв, характеризующих улучшение по этой схеме именования до сих пор сохранились, например, syslog-ng, aircrack-ng (Next Generation), vim (Vi IMproved), или имя автора: ksh (Korn SHell). За отсутствием повсеместного доступа к интернету и за тем фактом что написание софта под себя было нормой таких вариантов накапливались десятки и в каждой сети были свои. В 80-е был распространён редактор TECO (тико) и по аналогии свои редакторы многие программисты хакеры называли свои поделия такой-то-тико и сякой-то-тико, но один умный хакер решил пошутить и назвал свой редактор tint (Tint Is Not Teco). Шутка многим пришлась по вкусу и отчасти даже стала традицией именования. Ричард Мэттью Столлманом (rms) — один из тех толстых весёлых парней, кто в принципе любит пошутить и кому эта шутка в том числе нравилась. Когда он начал искать имя для своей свободной UNIX-подобной операционной системы он решил придерживаться шаблона «что-то не UNIX», но ни один из 26 возможных вариантов «?INU» не являлся словом и название получалось не такое уж интересное. В итоге волевым решением он сократил его на одну букву и получил классическое «GNU's Not Unix», которое с одной стороны следовало традиции, а с другой имело за собой шлейф вторых прочтений, среди которых «не UNIX от GNU» и «не UNIX от гну» итп. Вольный пересказ лекции самого rms.

пятница, 27 декабря 2019 г.

Как задать в gdb пути к библиотекам для core dump?

#gdb #linux


Есть coredump от упавшей программы, запущенной на другой машине. Есть библиотеки,
на которые coredump ссылается. Но путь к библиотекам при запуске софтины на другой
машине отличается от пути к библиотекам на машине, где запускается gdb.

Посему вопрос: как в gdb задать путь к этим библиотекам? 
    


Ответы

Ответ 1



мало того, что пути отличаются, так, скрее всего, отличаются и сами библиотеки. вам нужно получить ровно те же самые файлы, что использовались на «другой» машине. путь к иерархии скопированных библиотек можно указать с помощью: set sysroot путь или (это синоним): set solib-absolute-prefix путь подробности смотрите в info gdb или онлайн.

суббота, 21 декабря 2019 г.

Дублирование имен файлов в проектах С++

#cpp #qtcreator #gdb


Имею проект C++ под qmake с иерархической структурой TEMPLATE=SUBDIRS

Module1
   ModuleStaticLib1
   UnutTest1
Module2
   ModuleStaticLib2
   UnutTest2
Module3
   Приложение


В каждом подпроекте могут быть *.cpp файлы с одинаковыми именами


Module1/ModuleStaticLib1/Controller.cpp - реализация класса namespace Module1::Controller    
UnitTest1/Controller.cpp - юнит тест класса Module1::Controller   
Module2/ModuleStaticLib2/Controller.cpp - реализация Module2::Controller    
UnitTest2/Controller.cpp - юнит тест класса Module2::Controller


Работаю в qtcreator. Обратил внимание на странный баг при отладке, если установить
точку останова в  UnitTest1/Controller.cpp, она ставится также и в Module1/ModuleStaticLib1/Controller.cpp
(может и в другие одноименные файлы, но я гоняю один тест). В рамках одного модуля
имена файлов не повторяются.

Кроме того мой коллега, выразил сомнение в таком подходе, могут быть  проблемы со
сборкой(я не замечал). На сколько корректно использование одинаковых имен в разных
модулях, и чем может быть баг с точками оcтанова qtcreator или GDB?


QtCreator 3.5.81 
gcc version 4.8.4
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Linux Mint17


PS Демонстрация структуры "Глюкодрома" =)

    


Ответы

Ответ 1



По-моему, опция "Set breakpoints using a full absolute path" решает проблему с дублированием точек останова.

Ответ 2



Будет жуткий глюкодром - среда объединяет файлы с равными именами. Но гораздо хуже будет глюкодром в сознании человека, которому вы этой лазанье придется разбираться. Хотя бы из-за этого стоит уйти от такой структуры. UPD от 9 октября 2016. Qt creator в связке с MSVC2012 работает как попало, если в проекте есть одинаковые по именам файлы, он затирает одни объектники (*.obj) другими, более поздними, так как сваливает все в один каталог. В итоге - тонны ошибок при линковке.

среда, 10 июля 2019 г.

Имена массивов в си и арифметика указателей

В этой статье автор пытается рассказать о том, чем являются имена массивов в Си. Он показывает, что a и &a имеют одно и то же числовое значение, то разные типы. Имя a является указателем на первый элемент массива и имеет тип int *, а &a - то же самое, что &a[0], и является указателем на массив из трех чисел.
Пример в конце статьи:
preserve do :escaped (gdb) print a + 1 $10 = (int *) 0x7fff5fbff570 (gdb) print &a + 1 $11 = (int (*)[3]) 0x7fff5fbff578
И цитата автора: Note that adding 1 to a adds four to a’s address, whereas adding 1 to &a adds twelve!
Почему здесь написано, что к &a прибавляется 12, когда по логу видно, что прибавляется 8? Почему прибавление единицы к &a инкрементирует значение гораздо больше, чем прибавление единицы к a? Что это за игра с типами такая?


Ответ

По поводу первого вопроса
Почему здесь написано, что к &a прибавляется 12, когда по логу видно, что прибавляется 8?
Стоит обратить внимание, что в логе отображены результаты сложения, и между ними разница действительно 8 и это вводит в заблуждение. Но, чтобы узнать сколько прибавилось, нужно смотреть на начальный адрес
= preserve do :escaped (gdb) x/4xb a 0x7fff5fbff56c: 0x01 0x00 0x00 0x00 (gdb) x/4xb &a 0x7fff5fbff56c: 0x01 0x00 0x00 0x00
И если смотреть разницу относительно него, то можно увидеть, что в первом случае она равно 4, а во втором - 12 как и написано в статье.
Что касается второго вопроса
Почему прибавление единицы к &a инкрементирует значение гораздо больше, чем прибавление единицы к a? Что это за игра с типами такая?
то возможно поможет перевод аналогичного вопроса на английском
Имя массива обычно вычисляется как адрес первого элемента, так что array и &array имеют одинаковое значение (но разные типы, array+1 и &array+1 не будут равны, если длина массива больше одного элемента).
Есть два исключения из этого правила: когда имя массива является операндом sizeof или унарного & (address-of) имя указывает на сам массив, поэтому sizeof возвращает размер всего массива, а не размер указателя.
Для массива определенного как T array[size], array будет иметь тип T *. При инкрементировании его вы получите следующий элемент в массиве.
&array возвращает тот же адрес, но при этом тип указателя будет уже T(*)[size] - т.е. это указатель на весь массив, а не отдельный элемента. И когда вы увеличиваете этот указатель он добавляет размер всего массива, а не размер отдельного элемента.

суббота, 6 июля 2019 г.

Code::Blocks - GDB не видит точек останова в проекте CMake

Продолжая знакомиться с Code::Blocks наткнулся на непонятное поведение. Если проект создан с помощью CMake - GDB не видит точек останова в проекте, так же не работает выполнить до текущей позиции.. Выполняет весь код, без остановов.

чего пишет на это GDB:
Starting debugger: C:\MSVS\CodeBlocks\MinGW\bin\gdb32.exe -nx -fullname -quiet -args C:/__BuildSorce/T-CMAKE/t1/winext/codeblock/TestWchar2ext.exe done Setting breakpoints Debugger name and version: GNU gdb (GDB) 7.9.1 No source file named C:/__BuildSorce/T-CMAKE/t1/test/check_wchar2_MSVC.c. Temporary breakpoint 3 ("C:/__BuildSorce/T-CMAKE/t1/test/check_wchar2_MSVC.c:150") pending. Child process PID: 3408 [Inferior 1 (process 3408) exited normally] Debugger finished with status 0
На всякий случай добавил путь к исходнику исполняемого файла, он собственно один, не помогло..

Судя по всему он не может таки найти исходник check_wchar2_MSVC.c, как ему еще указать где искать?


Ответ

Если отладчик не видит точек останова, значит, информация о них не попала в скомпилированный исполняемый файл.
Для того, чтобы программу можно было отлаживать (а это не только точки останова, но и пошаговая трассировка и просмотр значений переменных), надо передать компилятору следующие параметры командной строки:
-g — снабдить исполняемый файл отладочной информацией, с помощью которой отладчик сможет сопоставить машинные инструкции строкам исходного кода. -Og — отменить все ранее объявленные -O-параметры и включить минимальный набор оптимизаций, не мешающих отладке. Так как Code::Blocks добавляет пользовательские параметры в конец командной строки компилятора, после своих, этот флаг позволяет временно переопределить настройки проекта на время отладки.

среда, 16 января 2019 г.

Роль организации GNU

Не могу понять роль организации GNU. Переводится как некий проект ***not Unix. Эм...ну если not Unix, то почему тогда их проект gdb это отладчик под Unix системы?


Ответ

Проект GNU (англ. The GNU Project) — проект по разработке свободного программного обеспечения (СПО), является результатом сотрудничества множества отдельных проектов. Проект был запущен программистом и сторонником СПО Ричардом Столлманом 27 сентября 1983 года в Массачусетском технологическом институте. Изначальной целью проекта было «разработать достаточно свободного программного обеспечения, чтобы можно было обойтись без программного обеспечения, которое не является свободным».
Текущая работа проекта GNU включает в себя разработку программного обеспечения, повышение осведомлённости, проведение политических кампаний и раздачу новых материалов.
Пожалуй, в контексте твоего вопроса, интереснее всего фраза
является результатом сотрудничества множества отдельных проектов
Манифест
Лицензии
Программы. Уверен, тебя заинтересует список.

Философию происходящего в этом проекте хорошо иллюстрирует существование нежно мною любимой LibreJS
дополнение к Firefox, позволяющее отказаться от выполнения несвободного JavaScript-кода. По мнению Ричарда Столлмана, проблема с JavaScript состоит в том, что код загружается без ведома пользователя, не давая возможности оценить степень его свободности перед загрузкой и воспрепятствовать выполнению проприетарного JavaScript-кода. Определение применяемой в JavaScript-коде лицензии производится через указание на сайте специальных меток или через анализ наличия упоминания лицензии в комментариях к коду. Кроме того, по умолчанию допускается выполнение тривиального JavaScript-кода, известных библиотек и кода с сайтов, занесённых пользователем в белый список.

пятница, 9 ноября 2018 г.

Дублирование имен файлов в проектах С++

Имею проект C++ под qmake с иерархической структурой TEMPLATE=SUBDIRS
Module1 ModuleStaticLib1 UnutTest1 Module2 ModuleStaticLib2 UnutTest2 Module3 Приложение
В каждом подпроекте могут быть *.cpp файлы с одинаковыми именами
Module1/ModuleStaticLib1/Controller.cpp - реализация класса namespace Module1::Controller UnitTest1/Controller.cpp - юнит тест класса Module1::Controller Module2/ModuleStaticLib2/Controller.cpp - реализация Module2::Controller UnitTest2/Controller.cpp - юнит тест класса Module2::Controller
Работаю в qtcreator. Обратил внимание на странный баг при отладке, если установить точку останова в UnitTest1/Controller.cpp, она ставится также и в Module1/ModuleStaticLib1/Controller.cpp (может и в другие одноименные файлы, но я гоняю один тест). В рамках одного модуля имена файлов не повторяются.
Кроме того мой коллега, выразил сомнение в таком подходе, могут быть проблемы со сборкой(я не замечал). На сколько корректно использование одинаковых имен в разных модулях, и чем может быть баг с точками оcтанова qtcreator или GDB?
QtCreator 3.5.81 gcc version 4.8.4 GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 Linux Mint17
PS Демонстрация структуры "Глюкодрома" =)


Ответ

По-моему, опция "Set breakpoints using a full absolute path" решает проблему с дублированием точек останова.