Почему отладчик lldb присваивает значение, когда я устанавливаю контрольную точку?

#c #debugging #lldb

#c #отладка #lldb

Вопрос:

В следующем коде на языке Си:

 #include lt;stdio.hgt;  int main(void) {  unsigned i = 1;  while (i)  {  i lt;lt;= 1;  }  return 0; }  

Сначала я компилирую с отладочной информацией следующим образом: gcc -g single-step.c Тогда я это делаю lldb a.out . Я хочу видеть, что я делаю , поэтому я делаю b main и run , после чего я устанавливаю свою точку наблюдения для i: watchpoint set variable i . Однако, когда я это делаю, lldb, похоже, присваивает значение переменной i, чего не должно быть
Watchpoint created: Watchpoint 1: addr = 0x16fdff498 size = 4 state = enabled type = w declare @ '/Users/d1ff1cult/Documents/KUL 2021-2022/IW/oefenzitting-c/les8-debugging/examples/single-step.c:5' watchpoint spec = 'i' new value: 53472
Это дает мне, казалось бы, совершенно случайное значение, так что же я делаю не так?
Я использую CLion для написания своего кода, но это происходит в терминале CLion, а также в моем собственном терминале macOS. Я также использую Mac M1.
Заранее спасибо!

Комментарии:

1. Вероятно, он отображает значение до i инициализации 1 , которое является отдельной операцией.

Ответ №1:

Юджин прав.

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

Я изменил программу, чтобы поместить ваш код в функцию (например) orig .

Я создал функцию fill , которая циклически заполняет свой кадр стека массивом int длиной 100.

От main , я звоню fill , а потом orig с b orig . Затем, выполнив команду watchpoint, я получаю значение 100.

Таким образом, ваша точка наблюдения отображает все, что происходит в кадре стека для того, что i назначено. То есть неинициализированное значение.

Вот программа тестирования, которую я создал:

 #include lt;stdio.hgt; #include lt;stdlib.hgt;  int orig(void) {  unsigned i = 1;   while (i) {  i lt;lt;= 1;  }   return 0; }  void fill(void) {  unsigned x[100];   for (int i = 0; i lt; 100;   i)  x[i] = rand(); }  int main(void) {   fill();  orig();   return 0; }  

Вот отладочный вывод:

 gt; lldb ./fix1 (lldb) target create "./fix1" Current executable set to './fix1' (x86_64). (lldb) b main Breakpoint 1: where = fix1`main   4 at fix1.c:29, address = 0x000000000040117b (lldb) b orig Breakpoint 2: where = fix1`orig   4 at fix1.c:7, address = 0x000000000040112a (lldb) run Process 193289 launched: '/tmp/watch/fix1' (x86_64) Process 193289 stopped * thread #1, name = 'fix1', stop reason = breakpoint 1.1  frame #0: 0x000000000040117b fix1`main at fix1.c:29  26 main(void)  27 {  28  -gt; 29 fill();  30 orig();  31   32 return 0; (lldb) c Process 193289 resuming Process 193289 stopped * thread #1, name = 'fix1', stop reason = breakpoint 2.1  frame #0: 0x000000000040112a fix1`orig at fix1.c:7  4 int  5 orig(void)  6 { -gt; 7 unsigned i = 1;  8   9 while (i) {  10 i lt;lt;= 1; (lldb) watchpoint set variable i Watchpoint created: Watchpoint 1: addr = 0x7fffffffdd6c size = 4 state = enabled type = w  declare @ '/tmp/watch/fix1.c:7'  watchpoint spec = 'i'  new value: 100  

Комментарии:

1. отладочная информация обычно не представляет инициализацию переменной — это может зависеть от пути и ее будет трудно представить. Он имеет тенденцию отслеживать только лексическую область переменных и их местоположение в этой области. Поскольку переменная входит в область действия, когда она определена, и отладчик не может определить, была ли она инициализирована, он будет сообщать о том, что находится в этой памяти, независимо от статуса инициализации значения.