Good evening.
Code:
// STD библиотеки и заголовки #include <stdio.h> #include <stdlib.h> #include <stdbool.h> // Windows библиотеки и заголовки #include <windows.h> // Пределы переменных #include <limits.h> // Подключение настроек #include <Settings.h> /* ПОТОКИ */ DWORD WINAPI SafeСycleThreadF(LPVOID); // Поток безопасного прохода /* Структуры */ // Структура простой задачи struct simple_task { unsigned int root; unsigned int* tail; }; // Структура буфера задач struct taskbuffer { unsigned long long int CurrNum; unsigned long long int* TaskCount; struct simple_task** Tasks; } TaskBuffer; // Структура графа struct graph_my { unsigned long long int count; unsigned int* freelist; unsigned int** grmatrix; } GHT; // Очередь процессов struct prlist { unsigned int root; unsigned int* tail; bool check; unsigned char status; }; // Оберка для очередей процессов struct PL { unsigned long long int count; struct prlist* gl; bool busy; bool found; } PL_L; /* Сигнатура функций */ unsigned char GetAvThreads(unsigned char); // Получение числа доступных потоков void PrintWelcome(); // Печать экрана приветствия void PrintSys(unsigned char); // Печать информации и системе bool Graph_Create(FILE**); // Печать графа void FileInput(); // Ввод, анализ и т.п. файла void Taskmgr_Initialize(); // Иницианализация диспетчера потоков void Taskmgr_Start(unsigned char); // Запуск диспетчера потоков ///////////////////////////////////////////////////////////////////// // // // ОСНОВНОЙ ПОТОК // // ///////////////////////////////////////////////////////////////////// int main() { /* ПЕРЕМЕННЫЕ */ unsigned int* Ccmass; // Массив, содержащий в себе цикл unsigned char avthreads; //Доступно потоков bool found; FILE* file = NULL; // Файл //////////////////// /* ОСНОВНОЙ ПОТОК */ //////////////////// // Изменение оформления консоли if (Styled_console == true) system("color F1"); // Вывод экрана приветствия if (Welcome_logo_show == true) PrintWelcome(); // Вычисляем кол-во ядер avthreads = GetAvThreads(ThreadLimit); // Вывод системных даных на экран if (SysInfo_show == true) PrintSys(ThreadLimit); // Ввод адресса FileInput(); // Постановка задач в список Taskmgr_Initialize(); // Небольшое исправление для потоков if (avthreads > 1) avthreads--; //Т.к. главный поток - тоже поток // Выполнение задач Taskmgr_Start(avthreads); // // Вывод /* found = false; for (positionnn = 0; positionnn < PL_count; positionnn++) { // Лог отладка printf("--------------------\n"); printf("%u", PL[positionnn].root);printf("\n"); printf("%u", PL[positionnn].tail[0]);printf("\n"); for (first = 1; first <= PL[positionnn].tail[0]; first++) { printf("%u", PL[positionnn].tail[first]);printf("\t"); }printf("\n"); printf("%u", PL[positionnn].check);printf("\n"); if (PL[positionnn].check == 8) { found = true; printf("Found cycle: "); kek = 1; while (PL[positionnn].tail[kek] != PL[positionnn].root) kek++; kek--; Ccmass = (unsigned int*)malloc((PL[positionnn].tail[0]-kek+2)*sizeof(unsigned int)); Ccmass[0] = PL[positionnn].tail[0] - kek + 1; first = 1; for (lol = kek+1; lol <= PL[positionnn].tail[0]; lol++) { Ccmass[first] = PL[positionnn].tail[lol]; first++; } Ccmass[Ccmass[0]] = PL[positionnn].root; for (first = 1; first <= Ccmass[0]; first++) { printf("%u", Ccmass[first]); if (first != Ccmass[0]) printf("->"); } printf("\n"); free(Ccmass); } } if (found == false) printf("Cycles not found!\n"); */ if (PauseOnExit == true) system("pause"); return 0; } ///////////////////////////////////////////////////////////////////// // // // Потоки безопасного выполнения // // ///////////////////////////////////////////////////////////////////// // Проход по графам и поиск циклов DWORD WINAPI SafeСycleThreadF(LPVOID t) { unsigned long long int position = 0; // Текущая позиция unsigned long long int i, j; // Тикер (Для тех нужд) unsigned char CurPos; // позиция во временном буфере // Присоединение к временному буферу CurPos = TaskBuffer.CurrNum; // Инициализация потока while (PL_L.gl[position].check != false) position++; PL_L.gl[position].check = true; PL_L.busy = false; // Показываем, что определили свой порядковый номер // Обнуленеие задач в временном буфере TaskBuffer.TaskCount[CurPos] = 0; // Ищем цикл if (PL_L.gl[position].tail[0] != 0) { for (i = 1; i <= PL_L.gl[position].tail[0]; i++) { if (PL_L.gl[position].root == PL_L.gl[position].tail[i]) PL_L.gl[position].status = true; PL_L.found = true; } } // Если не найден ни один цикл, то if (PL_L.gl[position].status != true) { for (i = 0; i < GHT.count; i++) { if (GHT.grmatrix[0][i] == PL_L.gl[position].root) { TaskBuffer.TaskCount[CurPos]++; TaskBuffer.Tasks[CurPos] = (struct simple_task*)realloc(TaskBuffer.Tasks[CurPos], TaskBuffer.TaskCount[CurPos]*(sizeof(struct simple_task))); TaskBuffer.Tasks[CurPos][TaskBuffer.TaskCount[CurPos]-1].root = GHT.grmatrix[1][i]; TaskBuffer.Tasks[CurPos][TaskBuffer.TaskCount[CurPos]-1].tail = (unsigned int*)malloc((PL_L.gl[position].tail[0]+2)*sizeof(unsigned int)); TaskBuffer.Tasks[CurPos][TaskBuffer.TaskCount[CurPos]-1].tail[0] = PL_L.gl[position].tail[0]+1; for (j = 1; j <= PL_L.gl[position].tail[0]; j++) { TaskBuffer.Tasks[CurPos][TaskBuffer.TaskCount[CurPos]-1].tail[j] = PL_L.gl[position].tail[j]; } TaskBuffer.Tasks[CurPos][TaskBuffer.TaskCount[CurPos]-1].tail[TaskBuffer.Tasks[CurPos][TaskBuffer.TaskCount[CurPos]-1].tail[0]] = PL_L.gl[position].root; } } } return 0; } ///////////////////////////////////////////////////////////////////// // // // Дополнительные Функции // // ///////////////////////////////////////////////////////////////////// // Вычисление ядер процессора unsigned char GetAvThreads(unsigned char limit){ // Пременные SYSTEM_INFO sysinfo; // Инфо о системе unsigned char Result; // Основной код // Вычисляем количество ядер процессора GetSystemInfo(&sysinfo); Result = sysinfo.dwNumberOfProcessors; // Применяем ограничитель if ((limit != 0) && (limit < Result)) { Result = limit; } // Фикс для странных Win ОС if (((Result > 250) || (Result < 1)) && (CPUFix == true)) Result = 1; return Result; } // Функция печати приветствия void PrintWelcome() { printf("Programm by Igor Burenkov\n"); printf("Variant: 6\n"); printf("You're welcome!\n\n"); } // Функция печати данных о системе void PrintSys(unsigned char avthreads) { // Переменные unsigned char cpucores; SYSTEM_INFO sysinfo; // Инфо о системе // Основной код cpucores = sysinfo.dwNumberOfProcessors; printf("---- System Info ----\n"); printf("\nAvailable Cores: "); printf("%u", cpucores); printf("\nAvailable Threads: "); if ((avthreads != 0) && (avthreads < cpucores)) { cpucores = avthreads; } printf("%u", cpucores); printf("\n"); printf("\n---------------------\n"); } // Ввод файла void FileInput(){ // Переменные FILE *file = NULL; char fadr[2048]; // Получение файла и создание графа while ((file == NULL)||(Graph_Create(&file)==false)) { if (file != NULL) printf("Broken file.\n"); printf("Please specify graph file adress:\n"); scanf("%s", fadr); file = fopen(fadr, "r"); if (file == NULL) printf("Wrong adress or file.\n"); } } ///////////////////////////////////////////////////////////////////// // // // Работа с графами // // ///////////////////////////////////////////////////////////////////// // Функция создания графа bool Graph_Create(FILE **file){ // Переменные unsigned long long int i, j, k, m; //Обычные тикеры для циклов unsigned int first, sec; // Если файл пуст if (*file == NULL) return false; // Считывание вершин fscanf((*file), "%u", &first); GHT.freelist = (unsigned int*)malloc(sizeof(unsigned int)); GHT.freelist[0] = 0; while (first != 0) { GHT.freelist[0]++; GHT.freelist = (unsigned int*)realloc(GHT.freelist, (GHT.freelist[0]+1)*sizeof(unsigned int)); GHT.freelist[GHT.freelist[0]] = first; fscanf((*file), "%u", &first); } // Cчитывание связей GHT.count = 0; GHT.grmatrix = (unsigned int**)malloc(2 * sizeof(unsigned int*)); GHT.grmatrix[0] = (unsigned int*)malloc(sizeof(unsigned int)); GHT.grmatrix[1] = (unsigned int*)malloc(sizeof(unsigned int)); while (fscanf((*file), "%u%u", &first, &sec) == 2) { if (sec != first) GHT.count++; GHT.count++; GHT.grmatrix[0] = (unsigned int*)realloc(GHT.grmatrix[0], GHT.count*sizeof(unsigned int)); GHT.grmatrix[1] = (unsigned int*)realloc(GHT.grmatrix[1], GHT.count*sizeof(unsigned int)); GHT.grmatrix[0][GHT.count - 1] = first; GHT.grmatrix[1][GHT.count - 1] = sec; if (sec != first) { GHT.grmatrix[0][GHT.count - 2] = sec; GHT.grmatrix[1][GHT.count - 2] = first; } } fclose(*file); // Удаление дублей m = 0; for (i = 0; i < GHT.count; i++) { for (j = i+1; j < GHT.count; j++) { if ((GHT.grmatrix[0][i] == GHT.grmatrix[0][j]) && (GHT.grmatrix[1][i] == GHT.grmatrix[1][j])) { for (k=j+1; k < GHT.count; k++) { GHT.grmatrix[0][k-1] = GHT.grmatrix[0][k]; GHT.grmatrix[1][k-1] = GHT.grmatrix[1][k]; } m++; } } } GHT.count = GHT.count - m; GHT.grmatrix[0] = (unsigned int*)realloc(GHT.grmatrix[0], GHT.count*sizeof(unsigned int)); GHT.grmatrix[1] = (unsigned int*)realloc(GHT.grmatrix[1], GHT.count*sizeof(unsigned int)); return true; } ///////////////////////////////////////////////////////////////////// // // // Работа с потоками // // ///////////////////////////////////////////////////////////////////// // Инициализация диспетчера потоков-задач void Taskmgr_Initialize(){ // Переменные unsigned long long int kek; // Постановка задач в список PL_L.count = GHT.freelist[0]; PL_L.gl = (struct prlist*)realloc(PL_L.gl, (PL_L.count)*(sizeof(struct prlist))); for (kek = 1; kek <= GHT.freelist[0]; kek++) { PL_L.gl[kek - 1].root = GHT.freelist[kek]; PL_L.gl[kek - 1].tail = (unsigned int*)malloc(sizeof(unsigned int)); PL_L.gl[kek - 1].tail[0] = 0; PL_L.gl[kek - 1].check = false; PL_L.gl[kek - 1].status = false; } // Доп. иницианализации PL_L.found = false; PL_L.busy = false; } // Запуск диспетчера потоков void Taskmgr_Start(unsigned char limit){ // Потоки HANDLE* SafeСycleCheck; // Поток вывода экрана приветствия // Переменные unsigned long long int position = 0; // Текужая позиция с списке задач unsigned char curlimit; // Кол-во потоков, используемых в данном конкретном цикле unsigned char i, j, k; // Тикер (Для циклов) // Цикл выполнения задач while (position < PL_L.count) { // Выставляем кол-во потоков if ((PL_L.count - position) < limit) curlimit = PL_L.count - position; else curlimit = limit; // Создаем массив потоков SafeСycleCheck = (HANDLE*)malloc(curlimit*sizeof(HANDLE)); // Создаем списоки буфера задач TaskBuffer.Tasks = (struct simple_task**)malloc(curlimit*sizeof(struct simple_task*)); TaskBuffer.TaskCount = (unsigned long long int*)malloc(curlimit*sizeof(unsigned long long int)); // Запускаем потоки for (i = 0; i < curlimit; i++) { // Ожидание инициализации предыдущего потока while (PL_L.busy != false); PL_L.busy = true; // Запуск потока TaskBuffer.CurrNum = i; SafeСycleCheck[i] = CreateThread(NULL, 0, SafeСycleThreadF, NULL, 0, NULL); } // Ожидание выполнения всех потоков for (i = 0; i < curlimit; i++) WaitForSingleObject(SafeСycleCheck[i], INFINITE); // Склейка и освобождение памяти временного буфера for (i = 0; i < curlimit; i++) { for (j = 0; j < TaskBuffer.TaskCount[i]; j++) { PL_L.count++; PL_L.gl = (struct prlist*)realloc(PL_L.gl, PL_L.count*(sizeof(struct prlist))); PL_L.gl[PL_L.count-1].check = false; PL_L.gl[PL_L.count-1].status = false; PL_L.gl[PL_L.count-1].root = TaskBuffer.Tasks[i][j].root; PL_L.gl[PL_L.count-1].tail = (unsigned int*)malloc((TaskBuffer.Tasks[i][j].tail[0]+1) * sizeof(unsigned int)); for (k = 0; k <= TaskBuffer.Tasks[i][j].tail[0]; k++) { PL_L.gl[PL_L.count-1].tail[k] = TaskBuffer.Tasks[i][j].tail[k]; } free(TaskBuffer.Tasks[i][j].tail); } free(TaskBuffer.Tasks[i]); } free(TaskBuffer.Tasks); // Освобождение памяти free(TaskBuffer.TaskCount); free(SafeСycleCheck); // Повышение позиции в списке position = position + curlimit; } } When you try to implement the release of memory - an error flies.
The exact location of the error in the code:
free(TaskBuffer.Tasks); I do not understand the reason for the error - can you help?
File for tests m.txt
1 2 3 4 5 6 0 1 1 1 2 3 3 2 1 6 2 6 3 4 4 3 2 Thank you!
PS Forgot the settings file Settings.h
#ifndef SETTINGS_H #define SETTINGS_H /////////////// /* НАСТРОЙКИ */ /////////////// // Технические const unsigned char ThreadLimit = 1; // Ограничение кол-ва потоков (Если 0, то ThreadLimit = CPU_cores, Если 1, то без учета главного потока, Если больше 1, то с учетом главного) const bool CPUFix = true; // Фикс числа CPU для запуска на странных ОС [Отключить, если у вас больше 250 ядер] // Визуальные const bool Welcome_logo_show = true; // Выводить приветствие const bool Styled_console = true; // Изменить оформление консоли const bool SysInfo_show = true; // Выводить на экран количество ядер // Отладка const bool PauseOnExit = true; // Выводить Сообщение-Паузу перед выходом #endif