LINUX.ORG.RU

[C/C++] как уловить изменения переменной?


0

0

Привет всем!

Столкнулся вот с такой проблемой. Есть цикл, в котором переменная переписываеться несколько раз:

int strangeVal = -1;
// черный ящик
for ( int i = 0; i < 10; ++i ) {
strangeVal = i;
}
// черный ящик

Это условная задача. На цикл for внимания не обращаем, так же не обращаем внимание на то что strangeVal присваивается значение i. Это может быть совсем другое значение.
Все что в цикле будем считать черным ящиком...
Главное понять смысл. Нужно каким-то волшебным образом при КАЖДОМ присваивании нового значения переменной strangeVal улавливать его, и где-то себе сохранять.

Так же проблема в том что ф-цию for и все что в ней ( черный ящик ) мы менят НЕ МОЖЕМ.

И так, возможно ли как небудь решить эту задачу?

Все что я нашел это volatile. Ну как я понял он сюда не подходит.

anonymous

> Так же проблема в том что ф-цию for и все что в ней ( черный ящик ) мы менят НЕ МОЖЕМ.

Велосипедистов с закрытыми библиотеками просят пройти на биореакторную обработку.

anonymous
()

а если обернуть strangeVal в прокси? Что-то в духе

template<typename T> class Proxy { 

T value;

Proxy<T>& operator=(const T& v) {
  value = v;
  // log this
}

const T& operator T() {
  return value
}

}

Proxy<int> strangeVal;

phoenix ★★★★
()

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

wfrr ★★☆
()

читать valgrind, просвещаццо. как раз когда поймёшь, как оно работает, поймёшь и глупость поставленой задачи.

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

Re^2: [C/C++] как уловить изменения переменной?

> а если обернуть strangeVal в прокси?

Не прокатит, ежели нельзя перекомпилировать "чёрный ящик" с переопределёнными типами. Т.е. без замены int на Proxy<int>.

gaa ★★
()

> Не прокатит, ежели нельзя перекомпилировать "чёрный ящик" с переопределёнными типами. Т.е. без замены int на Proxy<int>.

gaa прав. На простом примере так катит, а вот если ее использовать по назначению ( напр. передавать как параметр ) то не катит.

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

>читать valgrind, просвещаццо. как раз когда поймёшь, как оно работает, > поймёшь и глупость поставленой задачи.

> глупость поставленой задачи <

Если ты такой умный может наваляешь пару примеров?

anonymous
()

Если я правильно понял можно создать новый процесс и передать ему указатель на твою переменную, чтобы он в цикле сравнивал старое и текущее значение и если не совпадает писал лог в файл и дать ему найс поменьше. Можно запустить в gdb и элементарно точку наблюдения установить на переменной этой -break-watch i

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

Мне не нужно ничего хакать. 

Есть одно кривое API, которое я менять не в праве. 

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

Вот и приходится вылавливать значение таким способом...

Типо пример скомпилился, но не работает:

#include <iostream>

template < class T >
class Proxy {
   public:
      T value;

      Proxy<T>& operator=(T& v) {
         value = v;
         std::cout << value << std::endl;
      }

      T& operator ()() {
         return value;
      }
};

// черный ящик
void coolFunc ( int& strangeVal ) {
   for ( int i = 0; i < 10; ++i ) {
      strangeVal = i;
   }
}
// черный ящик

int main ( void ) {
   Proxy<int> strangeVal;

   coolFunc ( strangeVal() );

   return 0;
}

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

> Типо пример скомпилился, но не работает:

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

kondor ★★★
()

Ну чистА теоретически - на асме поставить хук на изменение по некоторому адресу возможно. x86 позволяет со времен 386. Выкинется прерывание, его ловить и т.д...

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

один раз. Вызываешь ф-цию. Ловишь все значения и все.

anonymous
()

Только хаками. Модификацией машинного кода или отслеживанием попыток записи в память.

Legioner ★★★★★
()

Не понятно, что значит "не можем".

Есть строчки кода, которые нельзя менять? Есть Файл исходника, который нельзя менять? Есть бинарник, который нельзя менять? Есть компьютер с бинарником, который нельзя трогать?

Если только строчки, то...

#include <stdio.h>

int tmp;
int & fun() {
printf ("in fun\n");
return tmp;
}

#define strangeVal (*f)()

void coolFunc ( int& strangeVal ) {
for ( int i = 0; i < 10; ++i ) {
strangeVal = i;
}
}

int main() {
printf("Start...\n");
coolFunc(fun);
printf("Done...\n");
}


Если бинарник, то аппаратные средства дебага либо вообще тупая эмуляция.

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

ммм... сорри, постановку задачи читал невнимательно. Нужны не факт обращения, а записываемое значения... Приведённый пример можно адаптировать, но это будет "не совсем то".

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

> Ну чистА теоретически - на асме поставить хук на изменение по некоторому адресу возможно. > x86 позволяет со времен 386. Выкинется прерывание, его ловить и т.д...

Если в функцию передается указатель куда возвращать результат (aka void probe(state * s)) - можно передавать заведомо невалидный - и обрабатывать SIGSEGV :]

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

не вопрос. 450 Eur штучка. дорого? иди в ПТУ, там дешевле. хочешь бесплатно? иди туда, где подают. я тебе, недоделку, подсказал метод и даже разжевал. если ты, тормоз, понять не способен — сдохни, очисти от себя планету.

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

>Но дело в том что при определенных обстоятельствах значений может быть несколько, а вернет то она только одно значение - последние, так как в цикле все перепишется. А мне нужны все значения.

Запускать два потока - ф-цию в отдельном потоке а в основном потоке в цикле опрашивать значение переменной - как только изменила значение накладывать pthread_mutex_lock и сохранять, потом снимать блокировку.

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

а что, mprotect() больше не котируют?

anonymous
()

Имхо единственный способ - пошаговое выполнение с наблюдением за состоянием переменной: отладчик или какая-нибудь виртуальная машина.

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

ну да, valgrind. только топикстартер у нас умный, он сам не может, ему код вынь да положь. небось, принципы работы valgrind даже не удосужился почитать.

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

>Запускать два потока - ф-цию в отдельном потоке а в основном потоке в >цикле опрашивать значение переменной - как только изменила значение >накладывать pthread_mutex_lock и сохранять, потом снимать блокировку.

Я еще раньше думал над этим. Но ИМХО не выйдет, да и не выходит.
Дело в том, что если создавать потоки pthread, то они не будут работать как 1-2-1-2-1-2... а могут работь как 1-1-1-2-2-1-2-1-1....
То есть тут нет ни какой гарантии что первый поток ( наша coolFunc() ) пройдет себе спокойно ( а так и будет, как как она маленькая ), а потом только переключится на вторую ( наша ф-ция проверки значений).
В итоге она хапанет только сново же таки последние значение.

>читать valgrind, просвещаццо. как раз когда поймёшь, как оно >работает, поймёшь и глупость поставленой задачи.

>Имхо единственный способ - пошаговое выполнение с наблюдением за >состоянием переменной: отладчик или какая-нибудь виртуальная машина

>не вопрос. 450 Eur штучка. дорого? иди в ПТУ, там дешевле. хочешь >бесплатно? иди туда, где подают. я тебе, недоделку, подсказал метод и >даже разжевал. если ты, тормоз, понять не способен — сдохни, очисти от >себя планету.

Сколько злости...
При чем сдесь valgrind или gdb? Мне что в README проги писать в зависимостях valgrind?!?

> gdb watch?

>ну да, valgrind. только топикстартер у нас умный, он сам не может, >ему код вынь да положь. небось, принципы работы valgrind даже не >удосужился почитать.

Не удосужился, но у меня это незаменимый инструмент..

И вообще я б сказал что в режиме отладки за изменением переменных лутше всего пользоватся gdb нежели valgrind.
valgrind незаменим в случае seglault.
Тогда он покажет кто и почему до это произвел.
С gdb это куда труднее сделать.

Но сдесь не идет разговор про хак какой-то проги, отладка или еще что-то.
Нужно огранизовать эту фичу нормально в коде.
Это обычная прога а не хакинг с использованием gdb + valgrind.

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

>При чем сдесь valgrind или gdb? Мне что в README проги писать в зависимостях valgrind?!?

«дядя Петя, ты совсем дурак?» что, выдрать из valgrind эмулятор ниак не получается?

>Но сдесь не идет разговор про хак какой-то проги, отладка или еще что-то.

именно что идёт. и именно про кривой хак, потому что нормальное решение — не болтать ерундой, а переделать реализацию. тебе же нужен хак зачем-то.

алсо, никакой злости у меня нет. пожелание очистить планету — просто пожелание.

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