Форум программистов, компьютерный форум, киберфорум
C (Си)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/14: Рейтинг темы: голосов - 14, средняя оценка - 4.86
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18

Ошибка Fatal glibc error: malloc.c:2599

04.01.2025, 20:16. Показов 10516. Ответов 34

Студворк — интернет-сервис помощи студентам
При компиляции ошибок нет.

При запуске в середине программы ошибка.
Code
1
Fatal glibc error: malloc.c:2599 (sysmalloc): assertion failed: (old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)
Нашел причину, но не могу до конца понять как устранить.

Открываю файл config (текстовый), в нем настройки программы. С новой строки (переменная = значение). Есть в конфиге следующая строка:
prefix_mobile = m

При наличии строки ошибок нет, но переменная в которую я копирую значение оказывается пустая. Когда строку из конфига убираю - происходит ошибка (выше).

1. Почему переменная char * prefix_mobile пустая, когда я копирую туда значение. Она не пустая сразу. Я делал вывод в консоль через printf и она выводится правильно. Ниже через строк 300-400 кода я вывожу эту переменную и она пустая.

2. Почему когда я убираю эту строку из конфига происходит ошибка (выше).

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

3. Читал статью в интернете. Про выделение памяти malloc. Есть информация что выделенная память растет в геометрической прогресиии, даже если передаю в malloc 9 байтов, то она округляется до 8 * 2 = 16. Если передаю malloc 129 (128 + 1), то память округляется до 256 (128 * 2). Это миф или есть основа для таких выводов? Может есть другое объяснение этой информации?


Есть альтернативные библиотеки для управление памятью?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.01.2025, 20:16
Ответы с готовыми решениями:

Ошибка при компиляции [Linker Fatal Error] Fatal: Expected a file name:
При компеляции Выдает Fatal: Expected a file name:

Ошибка [Linker Fatal Error] Fatal: Unable to Open file 'VCL.LI'
Прошу помощи: при попытке компиляции проекта возникает ошибка Fatal: Unable to Open file 'VCL.LI'. Builder пытается найти этот файл, но...

Ошибка [Linker Fatal Error] Fatal: Expected a file name:
При запуске любой программы пишет ошибку:-| Скоро курсовую сдавать,а я ее сделать не могу:cry: пишет ошибку: Fatal: Expected a file...

34
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
04.01.2025, 20:27
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
1. Почему переменная char * prefix_mobile пустая, когда я копирую туда значение. Она не пустая сразу. Я делал вывод в консоль через printf и она выводится правильно. Ниже через строк 300-400 кода я вывожу эту переменную и она пустая.
2. Почему когда я убираю эту строку из конфига происходит ошибка (выше).
Хрен его знает. Если не хочешь показывать код, то ты сайтом ошибся: тебе надо на форум экстрасенсов. Тут их нет.

Кликните здесь для просмотра всего текста
1
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
04.01.2025, 20:32  [ТС]
После удаления строки из конфига ошибка происходит вообще при парсинге другого значения из конфига.
Первый "Hello" выводится а второй - нет
когда возвращаю значение prefix_mobile в конфиг, ошибка исчезает **магия

C
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
// g.useragent_masks_desktop_count
if(main_data.config_key == 20){
 
    // realloc
    g.useragent_masks_desktop_malloc += sizeof(char *);
 
    printf("Hello\n");
    g.useragent_masks_desktop = realloc(g.useragent_masks_desktop, g.useragent_masks_desktop_malloc);
 
    printf("Hello\n");
    if(g.useragent_masks_desktop == NULL){
        printf("Error: loc memory [useragent_masks_desktop]\n");
        main_data.config_error = 1;
        break;
    }
 
 
    // malloc
    main_data.uli4 = strlen(main_data.char2) + 1;
    g.useragent_masks_desktop[ g.useragent_masks_desktop_count ] = (char *) malloc(main_data.uli4);
 
    if(g.useragent_masks_desktop[ g.useragent_masks_desktop_count ] == NULL){
        printf("Error: malloc [useragent_masks_desktop -> key]\n");
        main_data.config_error = 1;
        break;
    }
    memset(&g.useragent_masks_desktop[ g.useragent_masks_desktop_count ][0], 0, main_data.uli4);
 
 
    // cpy
    strcpy(g.useragent_masks_desktop[ g.useragent_masks_desktop_count ], main_data.char2);
    g.useragent_masks_desktop_count++;
}
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
04.01.2025, 20:40
Для чего вот это перераспределение памяти на +4 (или +8) байт?

0
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
04.01.2025, 20:50  [ТС]
Для этого realloc сделал вызов malloc ранее и ошибка перешла на вызов malloc, который находится ниже (тот код который отправил ранее) та же ошибка.

C
1
2
3
struct global {
    char ** useragent_masks_desktop; // 2d array
};
sizeof(char *) * useragent_masks_desktop_count = useragent_masks_desktop_malloc

sizeof(char *) - хранит ровно столько байт , сколько надо для адресации массивов на текущей системе. (вычитал из справочников). зависит от разрядности системы. на 32 битных это 4 а на 64 битных - 8.


Затем useragent_masks_desktop[ key ] = malloc(size)
это выделение памяти для значения в массиве с индексом key
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
04.01.2025, 20:55
realloc-то нахрена?
Зачем вообще вся эта фигня с перераспределениями памяти для загрузки сраного конфига?
Поставь там брейкпойнт и посмотри значения полей перед местом крэша по ассёрту, ёмаё. Отладчик именно для этого придумали. Мне отсюда не видно, что у тебя в конпуктере происходит.
1
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
04.01.2025, 20:59  [ТС]
Verevkin, значение вот

useragent_masks_desktop = xxx.|0.|2.12.|2.4.5.12.|2.12.6.|7.2.12.| 2.12.7.|2.12.8.|13.12.

это строка из конфига

значение xxx.
пытается выделить 5 байт памяти
C
1
2
main_data.uli4 = strlen(main_data.char2) + 1;
g.useragent_masks_desktop[ g.useragent_masks_desktop_count ] = (char *) malloc(main_data.uli4);
в этом коде!

strlen(main_data.char2) - 4 байта + 1 = 5 байтов.
значение xxx.
из переменной main_data.char2

тут и происходит ошибка. не выделает 5 байт памяти. сама строка с malloc и дает сбой ошибку (Fatal glibc error: malloc.c:2599)
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
04.01.2025, 21:03
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
sizeof(char *) - хранит ровно столько байт , сколько надо для адресации массивов на текущей системе. (вычитал из справочников).
Правильно, sizeof(char*) или sizeof(любой_тип*) равен размеру указателя для используемого компилятора.
Осталось понять, что за загадочная структура g и зачем она. char ** - это не 2d array, а динамический массив указателей.

Добавлено через 3 минуты
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
пытается выделить 5 байт памяти
А мож память выделяется, но ошибка происходит при записи указателя в ячейку массива g.useragent_masks_desktop[ g.useragent_masks_desktop_count ]?
Зачем ваще тут массив? Да, теоретически так можно, но геморроя не оберёсся. Сделай список и не надо будет юзать realloc().
0
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
04.01.2025, 21:05  [ТС]
Verevkin, прикол в том, что когда я возвращаю prefix_mobile в конфиг, то ошибка исчезает. с чем это может быть связано

Добавлено через 1 минуту
Verevkin, программа выдает ошибку сразу после выделения памяти. я не выхожу за пределы памяти (была бы другая ошибка).
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
04.01.2025, 21:08
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
программа выдает ошибку сразу после выделения памяти. я не выхожу за пределы памяти (была бы другая ошибка).
Ты уверен, что индекс массива правильный? А то в Сях массивы с нуля нумеруются, если чё...
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
прикол в том, что когда я возвращаю prefix_mobile в конфиг, то ошибка исчезает. с чем это может быть связано
Мне это ни о чём не говорит.
Советую выкинуть всю эту срань фтопку и написать хороший код с нуля (через список).
0
 Аватар для voraa
1284 / 1250 / 186
Регистрация: 21.01.2024
Сообщений: 5,752
04.01.2025, 22:24
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
((unsigned long) old_end & (pagesize - 1)) == 0
Здесь действительно один & ?
0
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 866
04.01.2025, 22:51
вообще ошибка очень похожа на то то где-то повредилась метаинформация malloc о расположении выделенных и пустых блоков. Тоесть где-то в программе есть выход за пределы массива.
ТС - если у вас есть своя библиотека для проверки целостности блоков памяти то самое время ей восползоваться.
или valgrind. Ну или написать свою - благо она не сложная но очень полезная.
Кстати из под отладчика ошибка может не проявляться.

C
1
g.useragent_masks_desktop[ g.useragent_masks_desktop_count ]
Вот так писать нельзя. сами себя запутаете ибо на момент выполнения переменная g.useragent_masks_desktop_count должна быть меньше на 1.

Цитата Сообщение от davidzhuchkov Посмотреть сообщение
3. Читал статью в интернете. Про выделение памяти malloc. Есть информация что выделенная память растет в геометрической прогресиии, даже если передаю в malloc 9 байтов, то она округляется до 8 * 2 = 16. Если передаю malloc 129 (128 + 1), то память округляется до 256 (128 * 2). Это миф или есть основа для таких выводов? Может есть другое объяснение этой информации?
кто его знает про какую библиотеку там писали. Я когда тестировал у себя на компе как работает malloc - то у моей версии выделялось кратно 16 байтам. независимо от размера блока. Когда я подменил malloc на jemalloc - то там совсем другое дело - там полная чехорда была с размерами блоков.
0
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
06.01.2025, 23:01  [ТС]
списки вещь хорошая. а как предложите реализовать Базу данных на списках?
есть другие способы выделять память? без malloc realloc free. Эта библиотека ведь также основывается на других

C
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
// DataBase
unsigned long long int db_malloc;
 
// -> [tables]
char ** db_table_names;                          // key_table
unsigned int db_tables_count;
unsigned long int db_tables_malloc_keys,
                  db_tables_malloc_values;
 
// -> [dirs]
unsigned int ** db_tables_dirs_names;            // [key_table] _ [dir_key]
unsigned int ** db_tables_dirs_write_counts;     // [key_table] _ [dir_key]
unsigned int * db_tables_dirs_count;             // [key_table]
unsigned long int db_tables_dirs_malloc;
 
// g->db_table_names[ g->db_tables_count ]
 
// columns [DataBase]
// char ** db_column_keys;                       // "[key_table]_[key_column]"
 
// -> [columns]
unsigned long int * db_column_offsets,
                    db_column_malloc_keys,       // [key_table]
                    db_column_malloc_values;
unsigned int * db_column_counts;                 // [key_table]
 
char ** db_column_names;                         // [offset, counts]
bool * db_column_types,                          // [offset, counts] - переделать из bool в unsigned int ...
                                                 // 0-9 (char ... unsigned long int ... long double) - доделать
 
     * db_column_positions;                      // [offset, counts], 0 - content, 1 - name_file
 
unsigned long int db_colimns_all;
 
// -> [cells]
char ** db_cells_char;
long long int * db_cells_int;
bool * db_cells_change;
unsigned long long int db_cells_malloc_keys,
                       db_cells_malloc_values;
 
unsigned long int db_cells_count,
                ** db_write_positions,           // [key_table]
                * db_increments;                 // [key_table]
unsigned long long int db_write_pos_1_malloc,
                * db_write_pos_2_malloc;         // [key_table]
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
06.01.2025, 23:19
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
списки вещь хорошая. а как предложите реализовать Базу данных на списках?
Никак не предложу.
Тыж сам сказал, что у тебя проблема с текстовым конфигом.
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
Открываю файл config (текстовый), в нем настройки программы.
Для этого списка достаточно. БД - это другое.

Кликните здесь для просмотра всего текста
1
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
06.01.2025, 23:37  [ТС]
На самом деле все можно сделать списками. Список имеет next, prew, parent и другие указатели на списки такого же типа.
Но ошибка может настигнуть и со списками. Тут надо использовать другой аллокатор памяти. Читал статью, что более 1кк записей в массиве также дает сбой malloc.c:2599. Тут надо брать исходный код malloc, realloc, free чтобы понять суть проблемы.

для списков также понадобится malloc
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
06.01.2025, 23:50
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
Тут надо брать исходный код malloc, realloc, free чтобы понять суть проблемы.
Тебе надо шашечки или ехать?
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
для списков также понадобится malloc
Кликните здесь для просмотра всего текста


Добавлено через 4 минуты
Эх, были времена, когда меня заставляли писать всякую срань под DOS. Да, за это платили неплохие бабки, но это была деградация мозгов. Я набросал кусок говнокода, который даже работал, могу подарить.

C
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
/* Модуль для работы с файлами настроек - заголовочный файл */
 
 
#ifndef inifiles_h
#define inifiles_h
 
#include "strutils.h"
#include <stdio.h>
 
 
/* -------------------------------- макросы --------------------------------- */
 
#define DEFAULT_FNAME   "settings.ini"
#define LETTERS         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"\
                        "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзиёклмнопрстуфхцчшщъыьэюя"
#define VALUE_CHARS     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"\
                        "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзиёклмнопрстуфхцчшщъыьэюя"
 
#define VALUE_DIVIDER   '='
#define COMMENT_DELIM ';'
#define MAX_STR_LEN     256 // длина буферов для работы с текстовым файлом
 
#define FIRST_INDEX     0
#define LAST_INDEX      -1
 
#define IS_LETTER(c)       strchr(LETTERS, c)
#define IS_VALID_SYMBOL(c) strchr(VALUE_CHARS, c)
 
/* ------------------------------ типы данных ------------------------------- */
typedef char  TCharBuf[MAX_STR_LEN];
 
typedef struct TIniItem
{
  string Ident;       // идентификатор
  string Value;       // строковое значение
  string Comment;     // комментарий
  int    Index;       // номер в списке по порядку добавления
  struct TIniItem* PrevItem; // указатель на предыд. в списке
  struct TIniItem* NextItem; // указатель на след. в списке
} TIniItem, *PIniItem;
 
typedef struct TIniFile
{
  string FileName; // имя файла
  FILE* F;         // декриптор файла
  PIniItem Items;  // связанный список контента
} TIniFile, *PIniFile;
 
typedef struct TStringPair
{
  TCharBuf Left, Right;
  char Divider; // символ разделитель
} *PStringPair;
 
/* -------------------------------- функции API ----------------------------- */
 
void ifClearFile(PIniFile);
void ifPrintItem(PIniItem);
string ifStringItem(string s, PIniItem item);
void ifPrintFile(PIniFile);
bool ifLoadFromFile(PIniFile, string);
WORD ifCount(PIniFile);
PIniItem ifFindItem(PIniFile, const string);
 
string ifReadString(PIniFile, const string, const string);
bool ifReadBool(PIniFile, const string, const bool);
int ifReadInt(PIniFile, const string, const int);
long ifReadLong(PIniFile, const string, const long);
float ifReadFloat(PIniFile, const string, const float);
double ifReadDouble(PIniFile, const string, const double);
 
#endif //inifiles_h
C
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/******************************************************************************/
/*                    Модуль для работы с файлами настроек                    */
/*                      Начат 05.10.2017   by Verevkin                        */
/*                      Версия 1.6, от 2 ноября 2019                          */
/******************************************************************************/
 
#include "inifiles.h"
 
/* ========================== сервисные функции ========================= */
bool ValidateIdent(string s)
{
  if (!s || !strlen(s) || !IS_LETTER(*s++)) return false;
  while (*s) if (!IS_VALID_SYMBOL(*s++)) return false;
  return true;
}
 
/*void AddItem2Log(string info, PIniItem item)
{
  char buf[256];
  sprintf(buf, "[%s] - %s = %s ; %s", info, item->Ident, item->Value, item->Comment);
  //Add2Log(buf);
} */
 
/* ======== функции для работы с динамической памятью (hardcore!) ======= */
 
// выделение памяти под опцию
PIniItem NewItem(string ident, string value, string comment)
{
  PIniItem result  = (PIniItem)malloc(sizeof(TIniItem));
  // выделение памяти с копированием:
  result->Ident    = strdup(ident);     // инициализация идентификатора
  result->Value    = strdup(value);     // значения
  result->Comment  = strdup(comment);   // и комментария
  result->PrevItem = NULL;              // очистка от мусора
  result->NextItem = NULL;              // очистка от мусора
  return result;
}
 
// освобождение памяти из-под опции с проверкой
void FreeItem(PIniItem item)
{
  if (item)
  {
    strfree(item->Ident);
    strfree(item->Value);
    strfree(item->Comment);
    free(item);
  }
}
 
void SetValue(PIniItem item, string value)
{
  if (!item) return;
  if (item->Value) free(item->Value); // если занято - освобождаю память
  item->Value = strdup(value);        // копирование значения
}
 
void SetComment(PIniItem item, string comment)
{
  if (!item) return;
  if (item->Comment) free(item->Comment); // если занято - освобождаю память
  item->Comment = strdup(comment);        // копирование значения
}
 
/* парсинг строки. если удачно - создаёт и возвращает объект TIniItem,
   иначе вернёт NULL.
   формат валидной строки:
   [пробелы, табы]ident[пробелы, табы]value[пробелы, табы][# комментарий]\0
 
   Алгоритм:
     1. найти начало комментария ";" скопировать в переменные всё, что слева и справа
     2. обрезать идент слева и справа (< #33) и проверить затем на валидность.
     3. скопировать в значение кусок строки от "=" до ";" (или до конца строки/0D/0A)
     4. скопировать в комментарий кусок от ";", если есть */
PIniItem ParseLine(string s)
{
  TCharBuf left, middle, right; // буфера под лексемы
 
  string divider_ptr = strchr(s, COMMENT_DELIM); // поиск начала комментария
 
  // обнуление буферов
  ZEROMEM(left, sizeof(TCharBuf));
  ZEROMEM(middle, sizeof(TCharBuf));
  ZEROMEM(right, sizeof(TCharBuf));
 
  if (divider_ptr) // если найден ";"
  {
    strtrimr(right, divider_ptr + 1); // копирую во временный буфер с очисткой справа
    *divider_ptr = 0; // и обрубаю по ";"
  }
 
  // оставшийся кусок строки распарсить как пару по "="
  divider_ptr = strchr(s, VALUE_DIVIDER); // поиск разделителя идента и значения
  if (!divider_ptr) return NULL; // если не найден "=", то это строка не содержит опции - на выход
 
  // сюда дойдёт, если оставшийся кусок - пара
  strtrim(middle, divider_ptr + 1); // копирую значение во временный буфер с очисткой слева и справа
  *divider_ptr = 0; // и обрубаю по "="
 
  // копирую идент во временный буфер с очисткой слева и справа
  strtrim(left, s);
  if (!ValidateIdent(left)) return NULL;
 
  // и только если есть валидный идент, состоящий из букв и цифр
  // и начинающийся с буквы, создаю новую запись.
  return NewItem(left, middle, right);    // выделение памяти, копирование и возврат
}
 
// получение ссылки на начальный, конечный элемент,
// или на элемент с номером 0 <= index < Count.
// для получения конечного элемента используется номер LAST_INDEX = -1.
// если элемента не существует, возвращается NULL.
PIniItem GetItem(PIniFile ini, int index)
{
  int idx = 0;
  PIniItem result = NULL;
  if (!ini || !ini->Items) return NULL;
 
  result = ini->Items;
  while (result)
  {
    if (index == LAST_INDEX && !result->NextItem) break; // найден последний
    if (index == idx) break; // найден по номеру
    result = result->NextItem; // переход на следующий
    idx++;
  }
 
  return result;
}
 
// добавление опции в конец списка. возвратит номер добавленного элемента
// или -1 при ошибке
int AddItem(PIniFile ini, PIniItem item)
{
  PIniItem last = NULL;
  if (!ini || !item) return -1;
 
  last = GetItem(ini, LAST_INDEX);
 
 
  if (last) last->NextItem = item, item->Index = last->Index + 1;
  else ini->Items = item, item->Index = 0;
 
  item->PrevItem = last;
  item->NextItem = NULL;
  return item->Index;
}
 
/* ------------------ функции, доступные извне --------------- */
// очистка списка параметров
void ifClearFile(PIniFile ini)
{
  PIniItem item, next = NULL;
  //printf("ifClearFile() - enter\n");
  if (!ini) return;
 
  item = ini->Items;
 
  while (item)
  {
    next = item->NextItem;
    FreeItem(item);
    item = next;
  }
  //printf("ifClearFile() - exit; ptr = %X\n", item);
 
  ini->Items = NULL;
}
 
void ifPrintItem(PIniItem item)
{
  printf("%s=%s;%s\n", item->Ident, item->Value, item->Comment);
}
 
string ifStringItem(string s, PIniItem item)
{
  sprintf(s, "%s=%s;%s", item->Ident, item->Value, item->Comment);
  return s;
}
 
void ifPrintFile(PIniFile ini)
{
  unsigned total = 0;
  PIniItem item = NULL;
 
  if (ini)
  {
    item = ini->Items;
 
    while (item)
    {
      ifPrintItem(item);
      item = item->NextItem;
      total++;
    }
  } // if
 
  printf(" [Total: %d]\n", total);
}
 
static char buffer_read[MAX_STR_LEN];
 
bool ifLoadFromFile(PIniFile ini, string FileName)
{
  PIniItem item;
  WORD count = 0;
 
  //printf("ifLoadFromFile() - enter\n");
  ZEROMEM(buffer_read, sizeof(buffer_read));
 
  ini->F = fopen(FileName, "rt");
  if (!ini->F) return false;
  ini->FileName = FileName;
 
  // чтение настроек из файла
  ifClearFile(ini);
 
  while (fgets(buffer_read, sizeof(buffer_read), ini->F))
  {
    //printf("buffer_read ---> %s", buffer_read); // debug
    assert(count < 10); // ЗОД : прога иногда виснет в этом цикле (а мож и не в этом)
    item = ParseLine(buffer_read);
    if (item) AddItem(ini, item), count++;
    //if (item) ifPrintItem(item); // debug
    ZEROMEM(buffer_read, sizeof(buffer_read));
  }
 
  // закрытие
  fclose(ini->F);
  //printf("ifLoadFromFile() - добавлено: %u\n", count);
  return true;
}
 
WORD ifCount(PIniFile ini)
{
  //printf("ifCount()\n");
  WORD result = 0;
  PIniItem item = ini->Items;
  while (item)
  {
    //AddItem2Log("count", item);
    result++;
    //printf(" ? result = %d\n", result);
    //getch();
    item = item->NextItem;
  }
 
  return result;
}
 
// поиск записи по иденту в списке. вернёт указатель на первый найденный
// или NULL, если не найден.
// Поиск регистрозависимый!
PIniItem ifFindItem(PIniFile ini, const string ident)
{
  PIniItem result = ini->Items;
 
  while (result)
  {
    if (strcmp(result->Ident, ident) == 0) break; // 0 ---> строки побайтно равны
    result = result->NextItem; // переход к след. элементу
  }
 
  return result;
}
 
// чтение строкового значения
string ifReadString(PIniFile ini, const string ident, const string defvalue)
{
  PIniItem item = ifFindItem(ini, ident);
  if (item) return item->Value;
  return defvalue; // по умолчанию
}
 
// чтение true / false
bool ifReadBool(PIniFile ini, const string ident, const bool defvalue)
{
  string s = ifReadString(ini, ident, NULL);
  if (!s) return defvalue; // не найден - по умолчанию
 
  // сравнение
  if (ARE_EQUAL(s, "false") || ARE_EQUAL(s, "FALSE")) return false;
  if (ARE_EQUAL(s, "true")  || ARE_EQUAL(s, "TRUE"))  return true;
  return defvalue; // некорректен - по умолчанию
}
 
// чтение 16-битного целого со знаком
int ifReadInt(PIniFile ini, const string ident, const int defvalue)
{
  int result;
  PIniItem item = ifFindItem(ini, ident);
  if (item && TryStr2Int(item->Value, &result)) return result;
  return defvalue; // по умолчанию
}
 
// чтение 32-битного целого со знаком
long ifReadLong(PIniFile ini, const string ident, const long defvalue)
{
  long result;
  PIniItem item = ifFindItem(ini, ident);
  if (item && TryStr2Long(item->Value, &result)) return result;
  return defvalue; // по умолчанию
}
 
// чтение 4-байтного вещественного со знаком
float ifReadFloat(PIniFile ini, const string ident, const float defvalue)
{
  float result;
  PIniItem item = ifFindItem(ini, ident);
  if (item && TryStr2Float(item->Value, &result)) return result;
  return defvalue; // по умолчанию
}
 
// чтение 8-байтного вещественного со знаком
double ifReadDouble(PIniFile ini, const string ident, const double defvalue)
{
  double result;
  PIniItem item = ifFindItem(ini, ident);
  if (item && TryStr2Double(item->Value, &result)) return result;
  return defvalue; // по умолчанию
}
2
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 866
07.01.2025, 00:00
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
Читал статью, что более 1кк записей в массиве также дает сбой malloc.c:2599.
Что ???

напишите маленькую библиотечку для контроля целостности выделяемой памяти - делов то на 10-15 кб кода на С
и проверьте. Я такой регулярно пользуюсь и довольно часто она меня выручает - бывает что заработавшись глупую ошибку просто незамечаю. А с такой библиотекой сразу и утечки видно и повреждения...

Так же один из вариантов - сделайте разбор конфига без использования выделения памяти.
при этом весь файл читается в один блок памяти и в процессе разбора более память не выделяется.
0
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
07.01.2025, 04:01  [ТС]
Aledveu, Если функция не смогла выделить буфер памяти, она возвращает NULL.
Я проверяю это. дело в том что прерывание программы происходит где то в самой функции malloc.

Видели исходный код malloc , realloc, free на github?
0
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 866
07.01.2025, 17:53
Цитата Сообщение от davidzhuchkov Посмотреть сообщение
Видели исходный код malloc , realloc, free на github?
Видел. И толку мне от этого никакого.

я вом говорил совершенно про другую систему - сделать обёртку над malloc которая при любых обращених и по вашему требованию в любом месте программы может проверить целостность подписей веред выделенным блоком и после - и так для всех блоков памяти которые ваша программа выделила с помощью malloc и аналогичных
1
0 / 0 / 0
Регистрация: 24.02.2021
Сообщений: 18
07.01.2025, 23:29  [ТС]
Aledveu, это не поможет. malloc просто критически уходит из программы.

Придумал следующий ход:

При запуске программы агрументом передавать сколько выделить памяти. Минимум памяти заложен в программе константой. Например передает 100 а минимум 200 мб, то программа проверит есть ли 200 и запустится (или выйдет).

Будет главный указатель и колл-во байт выделенной памяти. А затем пишу функцию и списки для управления этой памяти. выделение для чисел и строк. Просто буду устанавливать смещение, размер, указатель. все тоже самое, но в отличие от malloc я буду использовать #define func_name (args) {} , так код будет работать гораздо быстрее и я сам смогу обрабатывать ошибки. а точнее их избежать вовсе.

тему закрывать пока не буду. может найдется конкретный ответ, как исправить эту ошибку.

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

Добавлено через 2 часа 6 минут
Спасибо за ответ и ваш код, но я спрашивал про саму ошибку в любом контексте. А конфиг конечно я могу сделать.
Я закомментировал код, где появлялась ошибка, и ошибка перешла в другой участок программы(

Вообще в учебниках, которые я читал - рекомендуется сразу выделать память для программы а потом ее запускать. с запасом. так и сделаю.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.01.2025, 23:29
Помогаю со студенческими работами здесь

Ошибка при компилировании проекта. [Linker Fatal Error] Fatal: Unable to open file '*.OBJ'
Ребят, при компилировании проекта вылезает ошибка Fatal: Unable to open file 'ACPNG.OBJ' P.S. исходник проекта был куплен, а...

[Linker Fatal Error] Fatal: Could not open ~CBuilder6\Projects\Project1.exe (error code 5)
Инсталировал с++ builder 6. Запустил програму и попробывал компилировать пустую форму, чтобы протестировать програму. Она должна была мне...

Error C2760: синтаксическая ошибка / Fatal error C1004: непредвиденное обнаружение конца файла
Набыдлокодил следующее: Graph.h template&lt;class D&gt; class Graph { private: class Edge { private: int v1, v2;

Ошибка сборки "[Linker Fatal Error] Fatal: Expected a file name"
Выдаёт ошибку: Fatal: Expected a file name Пробовал настроить через Directories/Conditionals, не помогло. Код программы: ...

ошибка fatal error
при запуске exe вылетает ошибка что переменная i не инициализированна. #include &lt;iostream&gt; //using namespace std; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru