Я полагаю, что этот вопрос спрашивает, что происходит, а не "Это нормально?", Так что в этом случае (обычно) gdb
- ваш друг, модифицирующий программу для печати адреса этого во время построения, это внутри __func ифактический адрес объекта в контейнере, который мы видим: (адреса меняются, но расстояния и концепции должны оставаться неизменными)
# During constructors and captured value:
0x7fffffffda80 <- LambdaWrapper(100)
0x7fffffffdb00 <- LambdaWrapper(200)
0x7fffffffdb60 <- LambdaWrapper(300)
# Actual address of data stored in the container:
0x6170c0 <- LambdaWrapper(100)
0x6170e8 <- LambdaWrapper(200)
0x617110 <- LambdaWrapper(300)
Существует огромная разница в значениях, это потому, что создание происходит на стек , в то время как вектор выделяет данные с new
в куче 1009 *.
Из gdb
вызова info proc mappings
мы получаем список адресов памяти:
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x404000 0x4000 0x0 /[...]/LambdaOutOfScope/a.out
0x603000 0x604000 0x1000 0x3000 /[...]/LambdaOutOfScope/a.out
0x604000 0x605000 0x1000 0x4000 /[...]/LambdaOutOfScope/a.out
0x605000 0x637000 0x32000 0x0 [heap]
[...]
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
Но это не отвечает , почему изменяется только 100.Ответ на этот вопрос находится в кадрах стека : каждый вызов функции имеет локальное (обычно small ) пространство переменных для статических переменных (для которых нет new
для простоты).
Если мы проверим информацию стека с помощью info frame
, мы увидим, что:
(gdb) info frame
Stack level 0, frame at 0x7fffffffdbb0:
rip = 0x400deb in main (main.cpp:75); saved rip = 0x7ffff7495830
source language c++.
Arglist at 0x7fffffffdba0, args:
Locals at **0x7fffffffdba0**, Previous frame's sp is 0x7fffffffdbb0
Saved registers:
rbx at 0x7fffffffdb98, rbp at 0x7fffffffdba0, rip at 0x7fffffffdba8
Внутри main, поэтому 100 остается вне этого кадра, потому что оно не создается в main , а в Add
, чтобы проверить, когда внутри Add мы получаем:
(gdb) info frame 1
Stack frame at 0x1:
rip = 0x0; saved rip = <not saved>
Outermost frame: previous frame identical to this frame (corrupt stack?)
Arglist at 0x7fffffffdac8, args:
Locals at **0x7fffffffdac8**, Previous frame's sp is 0x7fffffffdad8
Saved registers:
rip at 0x7fffffffdad0
Таким образом, повреждение происходит, когда мы вызываем другую функцию, но , так как элементы выделеныв основном локальные они сохраняются , если вы поставите c.Add(400);
после 300, вы увидите, что он тоже поврежден (даже если построено после).
ПРИМЕЧАНИЕ : Iнадеюсь охватить все, но подробно об использовании gdb, в интернете есть множество руководств.