Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"

Рис. 15.1. Адресное пространство Linux/Unix, включая специальные области
Первым пакетом отладки, реализовавшим эту схему, был Electric Fence. Electric Fence является вставляемым заместителем для
malloc()
После компоновки программы с Electric Fence любой доступ за пределами выделенной памяти генерирует
SIGSEGV
1 /* ch15-badmem1.с --- плохо обращается с памятью */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 int main(int argc, char **argv)
7 {
8 char *p;
9 int i;
10
11 p = malloc(30);
12
13 strcpy(p, "not 30 bytes");
14 printf("p = <%s>n", p);
15
16 if (argc ==2) {
17 if (strcmp(argv[1], "-b") == 0)
18 p[42] = 'a'; /* коснуться за пределами границы */
19 else if (strcmp(argv[1], "-f") == 0) {
20 free(p); /* освободить память, затем использовать ее */
21 p[0] = 'b';
22 }
23 }
24
25 /* освобождение (p); */
26
27 return 0;
28 }
Эта программа осуществляет простую проверку опций командной строки, чтобы решить, как вести себя плохо:
-b
-f
Одним из способов использования Electric Fence, способом, который гарантированно работает на различных системах Unix и GNU/Linux, является статическая компоновка с ним вашей программы. Затем программа должна быть запущена из отладчика. (Документация Electric Fence явно указывает, что Electric Fence не следует компоновать с двоичным файлом готового изделия.) Следующий сеанс демонстрирует эту процедуру и показывает, что происходит для обеих опций командной строки:
$ <b>cc -g ch15-badmem1.c -lefence -о ch15-badmem1</b> /* Откомпилировать; компоновка статическая */
$ <b>gdb ch15-badmem1</b> /* Запустить из отладчика */
GNU gdb 5.3
...
(gdb) <b>run -b</b> /* Попробовать опцию -b */
Starting program: /home/arnold/progex/code/ch15/ch15-badmem1 -b
[New Thread 8192 (LWP 28021)]
Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <[email protected]>
p = <not 30 bytes>
Program received signal SIGSBGV, Segmentation fault.
SIGSBGV: GDB prints where
[Switching to Thread 8192 (LWP 28021)]
0x080485b6 in main (argc=2, argv=0xbffff8a4) at ch15-badmem1.c:18
18 p[42] = 'a'; /* коснуться за пределами границы */
(gdb) <b>run -f</b> /* Теперь попробовать опцию -f */
The program being debugged has been started already.
Start it from the beginning? (y or n) <b>y</b> /* Да */
Starting program: /home/arnold/progex/code/ch15/ch15-badmem1 -f
[New Thread 8192 (LWP 28024)]
Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <[email protected]>
p = <not 30 bytes>
Program received signal SIGSEGV, Segmentation fault. /* Снова SIGSEGV */
[Switching to Thread 8192 (LWP 28024)]
0x080485e8 in main (argc=2, argv=0xbffff8a4) at ch15-badmem1.c:21
21 p[0] = 'b';
На системах, которые поддерживают разделяемые библиотеки и переменную окружения
LD_PRELOAD
efence
ef
Хотя мы не описали механизмы подробно, GNU/Linux (и другие системы Unix) поддерживают разделяемые (shared) библиотеки, особые версии библиотечных процедур, которые хранятся в одном файле на диске, вместо того, чтобы копироваться в каждый отдельный двоичный исполняемый файл программы. Разделяемые библиотеки экономят дисковое пространство и могут сохранить системную память, поскольку все программы, использующие разделяемые библиотеки, используют одну и ту же копию библиотеки в памяти. Платой за это является замедление загрузки программы, поскольку программу и разделяемую библиотеку нужно подключить друг к другу прежде, чем программа сможет начать выполнение. (Обычно это прозрачно для вас, пользователя.)
Переменная окружения
LD_PRELOAD
ef
malloc()
ef