LINUX.ORG.RU

Господа пораскинем мозгами и инфой ... 3 Вопроса для обладателей 90 уровня ...

 , ,


0

2

Простой файлик. p.cpp

#include <iostream>
using namespace std;

string greeting = "hello";
string world("world");
string exclamation{'!'};

void p1(int i) {
    if(i == 1) cout << greeting + " 1" << endl;
    if(i == 2) cout << world + " 1" << endl;
    if(i == 3) cout << exclamation + " 1" << endl;
}
int main() {
p1(1);
p1(2);
p1(3);

    return 0;
}

g++ p.cpp получаем a.out Вопрос 1: Хочется например чтобы при чтении world gdb брейкнулся. То есть смысл простой при попытке чтения world и им подобным string`ам gdb останавливался … P.S. обращаю внимание тут string, а не с-строки. Вопрос 2: Таже история но нет исходников. Ну и вопрос 3: Если елф strip. Но в нем видны эти world и т.д. То есть по сути надо поставить брейк на доступ к памяти в виде string.



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

Как в GDB поставить breakpoint на попытку доступа к памяти, где лежит первый символ строки типа string C++?

Ответ ChatGPT:

В GDB можно поставить брейкпоинт на попытку доступа к памяти, где лежит первый символ строки типа std::string в C++. Для этого можно использовать команду watch, которая следит за изменениями в значении определенного адреса памяти.

Предположим, у вас есть следующий код:

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";
    std::cout << str << std::endl;
    str[0] = 'h'; // Изменение первого символа строки
    std::cout << str << std::endl;
    return 0;
}


Вы можете выполнить следующие шаги в GDB, чтобы поставить брейкпоинт на попытку доступа к первому символу строки:

Скомпилируйте программу с отладочной информацией:
g++ -g -o test test.cpp

Запустите GDB:
gdb ./test

Установите брейкпоинт в начале main функции и запустите программу:
(gdb) break main
(gdb) run

Найдите адрес первого символа строки str:
(gdb) p &str[0]

Допустим, GDB выведет что-то вроде:

$1 = (char *) 0x555555756040

Поставьте watchpoint на этот адрес:
(gdb) watch *(char *)0x555555756040

Продолжите выполнение программы:
(gdb) continue

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

Учтите, что std::string управляет памятью динамически, и адрес первого символа может измениться, если строка будет модифицироваться (например, при увеличении ее размера). В таком случае адрес нужно будет получить повторно и установить новый watchpoint.

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

очевидно, что при отладке на низком уровне придется в детали реализации лезть, смотреть на data() или как его там. В этом случае разницы между char* и string нету, хотя small string optimization может помешать. Нужно задачу точнее описывать, если хочется каких-то других решений

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

Надо писать так?

using std::cout;
using std::end;

?

Учитывая, что в С никаких namespace-ов нет, мне кажется, там лишнего и так приезжает с каждым include-ом куча всего. Поэтому я всё же не совсем понимаю суть проблемы. Ну приедет и приедет, кушать не просит же, программа от этого по-другому работать не начнёт.

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

Лучше писать std::…, да.

Очень длинно получится. std::cout << std::setprecision(3) << n << std::endl;

Можно, конечно, но это же классический пример синтаксического шума. Не знаю, как там в питоне, мне такой код не нравится. cout << setprecision(3) << n << endl выглядит лучше.

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

до безобидного using namespace std докопались, до бесполезного return 0 в конце - нет.

Э - эксперты

PS а еще std::endl смывает буфер на каждый чих. До этого они тоже не докопались :)

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

знаю конечно. Например знать язык, на котором пишешь - это хорошая привычка. А балаболить на темы, в которых не разбираешься - плохая.

С чем тебя и поздравляю, балабол :)

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

программа от этого по-другому работать не начнёт.

бггг

$ cat test.cpp

#include <iostream>
using namespace std;

struct A{
	A& operator << (int x){ std::cout<<"A::<<"<<x<<'\n'; return *this; }
};


int main(){
	A cout; cout<<1;
}

$ g++ -Wall test.cpp && ./a.out
A::<<1

Очень длинно получится

$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> len('std::cout << std::setprecision(3) << n << std::endl;')
52
>>> len('cout << setprecision(3) << n << endl;')
37
>>> 37/52
0.7115384615384616

О да, 30% экономии! Если хочется лаконичности это достигается другими способами, это же плюсы.

это же классический пример синтаксического шума.

нет.

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

до безобидного using namespace std докопались

см коммент выше, насколько он безобидный.

Э - эксперты

ну на Вашем то фоне и анонимус эксперт;-)

а еще std::endl смывает буфер на каждый чих.

Иногда это нужно.

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

Просто не надо писать такой странный код и всё будет хорошо. Я ничего страшного в этом коде не увидел. Естественно локальная переменная перекрывает верхние переменные.

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

Поэтому, если уж стоит задача защититься от такого, наверное надо сразу ::std::cout писать…

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

В C++ (и вроде в C) есть правило - что если из main не возвращается значение, то считается, что он вернул 0. Это конкретно для функции main такое правило, для других не распространяется. Конечно никто в своём уме так писать не будет, надо писать return 0 везде, чтобы не вызывать лишних вопросов.

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

Кроме cout там много всего есть, и вариантов конфликтов тоже довольно много.

надо сразу ::std::cout писать…

Можно придумать защиту от дурака, но только от неизобретательного.

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

А вот в golang - это ошибка. И все функции там указываются только с именем пакета в начале. И неиспользуемая переменная там - тоже ошибка. В общем, хороший инструмент, рекомендую.

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

А еще в стандарте K&R C если перед функцией не был указан тип, то предполагался int, поэтому запись функции main могла выглядеть так:

main() {
...
return 0;
}

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

обращаю внимание тут string, а не с-строки

Это у тебя в сырце string. А в бинаре запросто могут остаться только c-строки, в зависимости от того, что там компилятор наоптимизирует в итоге. У тебя string твои глобальные, и используются только в cout только для чтения содержимого. Никаких изменений инициализированных константой string у тебя нет, так что их в константы можно соптимизировать. И в итоге можно выкинуть всё std::string барахло при оптимизации потому что оно вообще никак не используется в коде. И откуда gdb возьмёт тебе твой string если его в бинаре не будет вообще?

В реале, для бинарника без сырцов обычно делаешь так (если на 100% уверен, что там именно std::string а не c-строки) - ищешь нужную с-строку, смотришь куда она копируется (или её адрес куда сохраняется), дальше пытаешься около этого адреса в данных найти структуру похожую на string, в начале у тебя всякий vtbl должен быть (см как C++ классы в памяти хранятся). Ну и используешь адрес где vtbl как начало твоего string для watch.

Но, как я уже написал - в твоём примере string вообще может не быть, если скомпилено с оптимизацией.

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

а причём тут го, если речь не про него? Тут двое из ларца попались на незнании элементарной вещи, быстренько ее загуглили и начали тупо отмазываться, неся чушь про какой-то там хороший тон.

Как говорится, на словах ты лев толстой, а в резюме и на собесах - опыт на плюсах в виде пары десктопных аппок для рог и копыт, в лучшем случае))

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

Да, надо писать std=c89, иначе не принимает. В будущих стандартах и int f() сделают эквивалентным int f(void). С каждым днём мы всё дальше от бога.

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

ну вообще-то это ты больше похож на нубаса, который кичится банальным знанием частных послаблений, тогда как опытные люди предпочитают не пользоваться этими послаблениями, чтобы не прививать себе плохие привычки

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

У меня скилла не хватает, чтобы придумать такое же перекрытие с std::cout

А скила отличить max(a, b) от std::max(a,b) хватает?

Если нет - подскажу ‘max(a,b)’ = это макрос, в с побочыми эффектами, если захочешь так max(foo(), bar())

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

Откуда ты взял этот макрос с побочными эффектами?

Из C. А в C он макрос, потому что туда темплэйты не завезли.

https://www.sourceware.org/git/?p=glibc.git;a=blob;f=misc/sys/param.h;hb=45b1e17e9150dbd9ac2d578579063fbfa8e1b327#l102

Гони в шею того, кто его написал.

дык std::max

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

Из C. А в C он макрос, потому что туда темплэйты не завезли.

В C нет такого макроса.

https://www.sourceware.org/git/?p=glibc.git;a=blob;f=misc/sys/param.h;hb=45b1e17e9150dbd9ac2d578579063fbfa8e1b327#l102

Это ужасно. Не пользуйся этим файлом.

дык std::max

В C нет такой конструкции.

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

std -это C++. Внезапно, да?

При чём тут С++ вообще? Ты сам пришёл с какими-то выдуманными макросами с побочными эффектами. Не понять тебя. Зачем тебе в С++ макросы? Ты какую задачу решить хочешь?

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

При чём тут С++ вообще? Ты сам пришёл с какими-то выдуманными макросами с побочными эффектами

Я, вообще-то про опасность писать using namespace std в C++, и привёл пример, а ты зачем - то манипуляциями занимешься.

Зачем -то ??? А так это - же LOR.

Не понять тебя

Ну ты прав, правда не я не понимаю в чём, но и неважно.

her_s_gory
()