Форум программистов, компьютерный форум, киберфорум
Pascal (Паскаль)
Войти
Регистрация
Восстановить пароль
Другие темы раздела
Pascal Установить в Debian что-нибудь похожее интерфейсом IDE на Turbo Pascal https://www.cyberforum.ru/ pascal/ thread1260862.html
Подскажите, что и как можно установить в Debian что-нибудь похожее интерфейсом IDE на Turbo Pascal. Спасибо. Добавлено через 3 минуты Да, ещё желательно, чтоб была совместимость с синтаксисом...
Pascal В массиве удалить все элементы кратные заданному числу
Задать три массива: один случайными целыми числами, второй вещественными положительными числами, третий - целыми числами в диапазоне значений от h до f. В первом массиве удалить все элементы кратные...
Вывести K-e степени чисел из заданного набора Pascal
Вариант4. Даны целые числа K, N и набор из N вещественных чисел: A1, A2, …,AN. Вывести K-e степени чисел из данного набора: (A1)^K, (A2)^K, …, (AN)^K. ^cтепень
Pascal Вычислить значение y в зависимости от х функции очень нуждаюсь в помощи.. нужно вычислить значение y в зависимости от х функции... https://www.cyberforum.ru/ pascal/ thread1260635.html
Pascal Задать массив вещественными числами от а до в, в количестве n и найти сумму всех цифр чисел кратных трем https://www.cyberforum.ru/ pascal/ thread1260321.html
Задать массив вещественными числами от а до в , в количестве n и найти сумму всех цифр чисел кратных трем
Задать массив целыми числами в диапазоне [0.100] и удалить все элементы , у которых последняя цифра 8 Pascal
Задать массив целыми числами в диапазоне и удалить все элементы , у которых последняя цифра 8
Pascal Если в строке, размещенной в динамической памяти, нет символа +, то оставить текст без изменения
Если в строке,размещенной в динамической памяти,нет символа +,то оставить текст без изменения, иначе каждую из цифр, предшествующую первому вхождению символа + заменить символом -.помогите сделать на...
Pascal Найти в последовательности самую длинную подпоследовательность, состоящую только из положительных чисел Найти в заданной последовательности самую длинную подпоследовательность, состоящую только из положительных чисел. используя текстовые файлы https://www.cyberforum.ru/ pascal/ thread1260267.html
Pascal Написать программу, в которой задается число, а компьютер его угадывает https://www.cyberforum.ru/ pascal/ thread1259883.html
помогите пожалуйста, написать программу, в которой я задаю число, а компьютер угадывает это число. количество попыток ограничено ?
Pascal Дан текст содержащий сведения об успеваемости учащихся. Определить средний балл каждого ученика Задача:Дан текст содержащий сведения об успеваемости учащихся, разделенное запятой.Каждое сведение содержит фамилию, имя ученика и оценки по 4 предметам, и заканчивается ".". Определить средний... https://www.cyberforum.ru/ pascal/ thread1259643.html
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
30860 / 20183 / 7874
Регистрация: 22.10.2011
Сообщений: 35,046
Записей в блоге: 6
22.09.2014, 21:16  [ТС] 0

Как не надо писать программы

22.09.2014, 21:16. Просмотров 17364. Ответов 4
Метки (Все метки)

Ответ


(продолжаем...)

Турбо Паскаль и нехватка памяти / ошибки №48, №49

В связи с возросшим количеством вопросов на темы "Программе не хватает памяти, что делать", "Ошибка компиляции №48 (или №49), помогите", "Программа вылетает с переполнением стека, куда копать?", хотелось бы привести основные моменты, на которые стоит обратить внимание при написании программ.

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


Ошибка №48 - Code segment too large (сегмент кода слишком большой).

Возникает в случае, когда размер кода, получаемого при компиляции программы, превышает 65520 байт (то есть, размер одного сегмента).
С этой ошибкой бороться относительно легко, и путей борьбы здесь несколько.
  1. Принимая во внимание тот факт, что код из разных модулей (Unit-ов) компилируется в разные сегменты, а программа на Паскале этих самых сегментов кода может иметь несколько, первое решение - "в лоб" - разбить программу на модули. С большой степенью вероятности ошибка исчезнет.
  2. Второй способ борьбы с ошибкой №48 - это уменьшение размеров самого кода, без разбиения его на модули. В основном, это касается программ, написанных по технологии Copy/Paste, то есть тех, которые чрезвычайно раздуты, и подпрограммы в которых зачастую различаются одной единственной строкой.

Как пример (из реальной программы, по которой был задан подобный вопрос):
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
Procedure op1;
const m2=15;
var mas2:array[1..m2] of string;
    c1,c2:string;
    cf:text;
begin
  mas2[1]:='1.Синий';
  mas2[2]:='2.Зеленый';
  mas2[3]:='3.Бирюзовый';
  mas2[4]:='4.Красный';
  mas2[5]:='5.Малиновый';
  mas2[6]:='6.Коричневый';
  mas2[7]:='7.Светло-серый';
  mas2[8]:='8.Темно-серый';
  mas2[9]:='9.Светло-голубой';
  mas2[10]:='10.Светло-зеленый';
  mas2[11]:='11.Светло-бирюзовый';
  mas2[12]:='12.Светло-красный';
  mas2[13]:='13.Светло-малиновый';
  mas2[14]:='14.Желтый';
  mas2[15]:='15.Белый';
  x1:=100;
  y1:=100;
  cleardevice;
  outtextxy(150,50,'Введите номер цвета текста');
  settextstyle(4,0,1);
  for  b1:=1 to 15 do
  begin
    setcolor(b1);
    outtextxy(x1,y1,mas2[b1]);
    y1:=y1+30;
  end;
  readln(lc);
  cvet:=lc;
  assign(cf,'config.ini');
  reset(cf);
  readln(cf,c2);
  c2:='';
  read(cf,c2);
  close(cf);
  assign(cf,'config.ini');
  rewrite(cf);
  str(lc,c1);
  writeln(cf,c1);
  writeln(cf,c2);
  close(cf);
  v_menu;
end;
Procedure op2;
const m2=15;
var mas2:array[1..m2] of string;
    c1,c2:string;
    cf:text;
begin
  mas2[1]:='1.Синий';
  mas2[2]:='2.Зеленый';
  mas2[3]:='3.Бирюзовый';
  mas2[4]:='4.Красный';
  mas2[5]:='5.Малиновый';
  mas2[6]:='6.Коричневый';
  mas2[7]:='7.Светло-серый';
  mas2[8]:='8.Темно-серый';
  mas2[9]:='9.Светло-голубой';
  mas2[10]:='10.Светло-зеленый';
  mas2[11]:='11.Светло-бирюзовый';
  mas2[12]:='12.Светло-красный';
  mas2[13]:='13.Светло-малиновый';
  mas2[14]:='14.Желтый';
  mas2[15]:='15.Белый';
  x1:=100;
  y1:=100;
  c1:='';
  c2:='';
  cvet2:=0;
  cleardevice;
  outtextxy(150,50,'Введите номер цвета фона');
  settextstyle(4,0,1);
  for b1:=1 to 15 do
  begin
    setcolor(b1);
    outtextxy(x1,y1,mas2[b1]);
    y1:=y1+30;
  end;
  readln(lc);
  cvet2:=lc;
  assign(cf,'config.ini');
  reset(cf);
  read(cf,c1);
  close(cf);
  assign(cf,'config.ini');
  rewrite(cf);
  str(lc,c2);
  writeln(cf,c1);
  writeln(cf,c2);
  close(cf);
  x1:=0;
  y1:=0;
  v_menu;
end;
Чем различаются процедуры? Правильно, в одном случае работаем с цветом самого текста, в другом - с цветом фона. Все. Больше - никакой разницы. А в сегменте кода место занимают обе процедуры (а ведь вполне достаточно одной, с одним дополнительным параметром). Хотя, в этих процедурах можно сделать ещё кое-что, но об этом я скажу чуть позже.
Отвлечемся ненадолго от ошибки №48, и посмотрим ...

Ошибка №49: Data segment too large (слишком большой сегмент данных)

Это происходит в случае, когда общий размер данных (глобальных данных, нужно заметить, потому что локальные размещаются не в сегменте данных) всех модулей превышает отведённый для них размер в 65520 байт. Простым разбиением на модули эту ошибку побороть нельзя: дело в том, что программа на Паскале может содержать несколько сегментов кода, и только один (общий для всех модулей) сегмент данных. Так что, если каждый из ваших модулей по отдельности компилируется - это ещё ничего не значит, при линковке exe-файла все ещё может "всплыть" сообщение об ошибке №49. Например:
Первый модуль:
Pascal
1
2
3
4
5
unit u01;
interface
var a: array[1 .. 10000] of longint;
implementation
end.
Второй модуль:
Pascal
1
2
3
4
5
unit u02;
interface
var b: array[1 .. 10000] of longint;
implementation
end.
Основная программа:
Pascal
1
2
3
4
5
6
7
8
9
10
11
uses u01, u02;
begin
  {
    если этого не сделать, то описания массивов
    будут просто проигнорированы, массивы A и B
    не будут включены в EXE
  }
  a[1] := 1; b[1] := 1; 
  
  writeln;
end.
Каждый модуль в отдельности прекрасно компилируется, при попытке "собрать" основную программу получаем вышеназванную ошибку.
Но и с этой ошибкой можно бороться. И тоже не одним способом:

Способ первый - проверяем, действительно ли нужны массивы типа LongInt. Как пример: нужно хранить в массиве рост 10000 школьников с точностью до сантиметра. И зачем тут longint? Достаточно типа byte (поправьте меня, если я ошибаюсь, но рост более 255 сантиметров для школьника - глупо), экономия четырехкратная. После изменения базового типа на byte даже только в одном из модулей мы избавляемся от "ошибки №49".

Особое внимание обратите на строковые типы: по умолчанию для string-а резервируется 256 байт. Это не всегда нужно, можно существенно уменьшить размер данных ограничением длины строки через string[длина].

То же самое касается вещественных типов: вместо использования real (6 байт) используем single (4 байта). Во-первых, экономия памяти в случае использования массивов, во вторых - увеличение быстродействия программы (тип real вообще очень медленный, поскольку он является "чужеродным" для сопроцессора, и его конвертация в сопроцессорный тип занимает кучу времени).

Способ второй - используем динамическое выделение памяти вместо статического, в результате данные хранятся не в сегменте данных, а в "куче", следовательно, опять избавляемся от ошибки №49:
Модуль №1
Pascal
1
2
3
4
5
6
7
8
9
unit u01;
interface
type
  ta = array[1 .. 10000] of longint;
var
  a: ^ta;
 
implementation
end.
Модуль №2
Pascal
1
2
3
4
5
6
7
8
unit u02;
interface
type
  tb = array[1 .. 10000] of longint;
var
  b: ^tb;
implementation
end.
Основная программа:
Pascal
1
2
3
4
5
6
7
8
uses u01, u02;
 
begin
  new(a); new(b); { выделяем память под оба массива }
  a^[1] := 1; b^[1] := 1;
  { ... }
  dispose(a); dispose(b); { освобождаем память }
end.
Поскольку размер "кучи" больше размера сегмента в 10 раз, то таким образом можно работать с данными гораздо большего объема.

Вернуться к обсуждению:
Как не надо писать программы
5
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.09.2014, 21:16

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Надо ли в конце программы до end писать readln
Надо ли в конце программы до end писать readln, чтобы просто курсор перешел на след. строку и когда...

Помогите писать на С++ через шаблоны. Консуле я писал, но надо писать исползуя шаблоны
В одномерном массиве, состоящем из п вещественных элементов, вычислить: 1) количество элементов...

Как создать программу которая бы выводила рандомно примеры и надо было правильно писать ответы
Как написать программу которая рандомно ставила примеры и надо было только писать правильные ответы...

как писать программы
как мне можно написать программу,и что для этого нужна???подскажите пожалуйста

0
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.