Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
1

Ошибка доступа к памяти при работе с потоками

04.10.2013, 21:23. Просмотров 1070. Ответов 16
Метки нет (Все метки)

проблема в следующем
в оконном приложении( среда разработки C++ Builder XE3)
создаю при нажатии кнопки "Run" поток
C++
1
HANDLE MainThread=CreateThread(NULL,0,MainThreadFunc,DOMT,0,&dwMainThreadId);
собственно в этом потоке происходит следующее
C++
1
2
3
4
5
for(int i=0;i<ThrCount;i++)
{
tmp->C->Items->Add(IntToStr(i));
Threads[i]=CreateThread(NULL,0,ThreadFunc,d[i],0,&dwThreadId[i]);
}
И уже в этих потоках по частям табулируеться нужная мне ф-ция,
И когда я пытаюсь закрыть один из созданных потоков, выскакивает ошыбка доступа к памяти

C++
1
2
3
4
5
void __fastcall TForm2::Button3Click(TObject *Sender)
{
int c=StrToInt(ComboBox2->Text);
TerminateThread(*(Threads+c),*(dwErrorCodes+c));
}
как вcе-таки завершыть один из этих потоков?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.10.2013, 21:23
Ответы с готовыми решениями:

Ошибка при работе с потоками
void __fastcall TForm1::FormCreate(TObject *Sender) { haha *Thr = new haha(true);...

Ошибка доступа при работе с Mutex
Как решить эту ошибку?! void CheckRepeatRun() { HANDLE hMutex = CreateMutex( NULL, 0,...

Ошибка доступа при работе с изображениями в DrawGrid
//при нажатии на кнопку в 1 ячейке 1 столбце должно появляться изображение, но выдает ошибку...

Ошибка доступа при работе нового потока с формой
Доброго времени суток, дорогие форумчане! Помогите устранить проблему: при запуске потока, который...

Ошибка при работе с потоками
Есть две функции: одна закидывает изображения в вектор, а вторая забирает их оттуда и обрабатывает....

16
Убежденный
Ушел с форума
Эксперт С++
16244 / 7311 / 1182
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
05.10.2013, 11:07 2
TerminateThread - это аварийное уничтожение потока.
Его следует применять только когда ничего другого не остается.
Например, если поток повис. Штатный способ завершить поток -
отправить ему соответствующий сигнал. Например, Win32 event.
Поток завершается, когда выходит из своей функции.
После этого только останется закрыть все хэндлы, которые
на него ссылаются.
0
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 11:46  [ТС] 3
Но, также Не работает и SuspendThread как и резюм...
0
Убежденный
Ушел с форума
Эксперт С++
16244 / 7311 / 1182
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
05.10.2013, 11:49 4
Цитата Сообщение от fakelessjohny Посмотреть сообщение
Но, также Не работает и SuspendThread как и резюм...
Приведите минимальный код, воспроизводящий проблему.
0
05.10.2013, 11:49
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 13:34  [ТС] 5
C++
1
2
3
4
5
void __fastcall TForm2::Button2Click(TObject *Sender)
{
int c=StrToInt(ComboBox2->Text);
SuspendThread(*(Threads+c));
}
я думаю проблема в том что я создаю потоки из другого потока, но ведь переменная HANDLE *Thread у меня глобальная, так что я через дескриптор вроде должен иметь доступ к любому потоку.
Может скинуть сюда полний код програми в виде прикрепленного файла?
0
Avazart
Эксперт С++
7922 / 5742 / 570
Регистрация: 10.12.2010
Сообщений: 26,306
Записей в блоге: 17
05.10.2013, 13:46 6
1. Используй TThread в место WinApi (в нем предусмотрена синхронизация с "окнами")
2. Не используй "Suspend" так как это может привести к блокировкам.
1
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 14:53  [ТС] 7
Цитата Сообщение от Avazart Посмотреть сообщение
1. Используй TThread в место WinApi (в нем предусмотрена синхронизация с "окнами")
2. Не используй "Suspend" так как это может привести к блокировкам.
я то не против использовать TThread но в универе тема WinApi управление потоками, и нужно обязательно использовать WinApi
+ одно из условий возможность приостановить исполнение потока.
0
Avazart
Эксперт С++
7922 / 5742 / 570
Регистрация: 10.12.2010
Сообщений: 26,306
Записей в блоге: 17
05.10.2013, 15:42 8
Ну без полного кода и описания, ничего нельзя сказать толком...
0
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 16:03  [ТС] 9
MainOS1.cpp.txt

ThreadThings.cpp.txt

ThreadThings.h.txt
0
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 16:04  [ТС] 10
Если не сложно обьясните в чем моя ошибка
0
Avazart
Эксперт С++
7922 / 5742 / 570
Регистрация: 10.12.2010
Сообщений: 26,306
Записей в блоге: 17
05.10.2013, 16:27 11
Ну если выкладываешь, так выкладывай либо код, либо исходники проекта архивом полностью.

Добавлено через 5 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DWORD WINAPI ThreadFunc(PVOID pParam)
{
long double s,si,y,eps=0.000001;
DATA_OF_THREAD *dDat=(DATA_OF_THREAD*)pParam;
TMemo *Output=dDat->M;
DWORD dwThreadFunc;
dwThreadFunc=0;
for(double x=dDat->BEGIN;x<dDat->END;x+=dDat->STEP)
{
y=pow((1+x),-1.0);
s=1;
si=x;
while(fabs(y-s)>eps)
{
    s-=si;
    si=si*x*(-1);
 
}
 
    Output->Lines->Add("X: "+FloatToStr(x)+L" |Y: "+FloatToStr(y)+L" |F(X): "+FloatToStr(s));
}
  return dwThreadFunc;
}
Ну вот :
C++
1
Output->Lines->Add("X: "+FloatToStr(x)+L" |Y: "+FloatToStr(y)+L" |F(X): "+FloatToStr(s));
этого делать в потоке нельзя, именно поэтому я и говорил про синхронизацию с помощью TThread.
А с помощью WinApi тут нужно отсылать сообщения Memo через SendMessage() полагаю.

Добавлено через 3 минуты
Думаю будет легче если ты опишешь задание, ибо смотреть в той код и гадать что ты хотел сделать...
0
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 16:59  [ТС] 12
тоесть нельзя передавать в поток параметром компоненты билдера??
ну задание звучит так
"Реализовать табуляцыю функции заданой разложением в ряд Тейлора в 2-х 4-х 8-ми потоках
Измерить время работы потоков и время работы всего процеса при помощи функций WinApi
Для каждого потока реализовать возможность его запуска, приостановления, и остановки.
0
Avazart
Эксперт С++
7922 / 5742 / 570
Регистрация: 10.12.2010
Сообщений: 26,306
Записей в блоге: 17
05.10.2013, 17:11 13
Цитата Сообщение от fakelessjohny Посмотреть сообщение
тоесть нельзя передавать в поток параметром компоненты билдера??
Как бы можно... нельзя использовать все что вызывает прямым или косвенным способом перерисовку в компонентах VCL (другие сложные механизмы)

При работе с потоками, в том числе VCL всегда стоит вопрос синхронизации.
В данном случае тут либо через TThread и его метод Syncronize() либо через потокобезоспасные ф-ции WinApi нужно реализовывать взаимодействие(синхронизацию).

Кроме того синхронизация "тормозит" работу потока, поэтому лучше накапливать данные, и только после завершения потока выводить данные в компоненты.
0
fakelessjohny
0 / 0 / 0
Регистрация: 10.01.2013
Сообщений: 59
05.10.2013, 17:20  [ТС] 14
но почему же все неплохо работало когда не было MainThreadFunc, тоесть когда я запускал все эти потоки напрямую из собития OnClick.. разве что при 8 потоках, переставало реагировоть окно, то есть я не мог из комбо бокса выбрать какой из потоков приостановить, или возобновить, при этом в Memo послушно приходили данные из всех этих потоков. 3,4, 5 потоков работали без проблем.
Разве в таком случае проблема в передаче в поток Memo?

Добавлено через 1 минуту
чтобы главное окно не подвисало , мне посоветовали использовать поток, в котором все другие потоки будут создаваться, как иначе это можно исправить, не прибегая к синхронизации, так как преподаватель говорит что нужно оставить синхронизацию для следующих лабораторних..
0
gumi250
431 / 398 / 57
Регистрация: 06.02.2012
Сообщений: 1,373
05.10.2013, 17:25 15
как написал Avazart VCL без синхронизации никак, без синхронизации только WinApi.

Не по теме:

А у нас сейчас преподы ничего не объясняют, а только спрашивают?

0
Avazart
Эксперт С++
7922 / 5742 / 570
Регистрация: 10.12.2010
Сообщений: 26,306
Записей в блоге: 17
05.10.2013, 17:29 16
Да дело в том что если без синхронизации то программа может периодически падать, а не постоянно...
В основном падения наблюдаются когда начинаешь таскать форму по экрану во время того когда поток пытается выводить данный - тут происходит "конфликт" и программа виснет намертво"

У тебя вероятно есть еще какие то еще ошибки, я детально не вникал.

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от gumi250 Посмотреть сообщение
А у нас сейчас преподы ничего не объясняют, а только спрашивают?
нет не только спрашивают, еще дезинформируют ...

1
kzru_hunter
1067 / 782 / 100
Регистрация: 01.02.2011
Сообщений: 1,795
Записей в блоге: 1
06.10.2013, 10:10 17
fakelessjohny Попробуй в этом коде разобраться. Тут представлен пример взаимодействия с vcl компонентами из другого потока без использования заточенного под это дело Thread::Synchronize.
Вобщем, для того чтобы из другого потока, например, добавить строку в Memo, нужно заставить основной поток самому добавить эту строку в Memo. Для этого нужно передать оконной процедуре основного потока специальное сообщение, обработав (обработчик пишет сам разразработчик) которое будет вызвана функция, которая в свою очередь добавит строку в Memo. Почти тоже самое делает Syncronize.

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
//---------------------------------------------------------------------------
 
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop
 
#include "Unit1.h"
 
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
 
DWORD WINAPI ThreadFunc( LPVOID param);
 
LRESULT CALLBACK MyWindowProc
(
    HWND hwnd,  // handle of window
    UINT uMsg,  // message identifier
    WPARAM wParam,  // first message parameter
    LPARAM lParam   // second message parameter
);
 
struct TMyData
{
        HANDLE FormHandle;
        TMemo *Memo;
        char *Text;
};
 
FARPROC MyOldWndProc;
void SyncFunc(LPVOID param);
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        // ïîäìåГ*ГїГҐГ¬ îêîГ*Г*ГіГѕ ïðîöåäóðó
        MyOldWndProc = (FARPROC)SetWindowLong(this->Handle, GWL_WNDPROC, (LONG)MyWindowProc);
 
        for ( int i = 0; i < 4; i++ )
        {
                // Гі ГЄГ*æäîãî ïîòîêГ* áóäåò ñâîé ýêçåìïëÿð Г¤Г*Г*Г*ûõ, êîòîðûé Г®Г* îêîГ*Г·Г*Г*ГЁГЁ îáðГ*áîòêè äîëæåГ* áóäåò îñâîáîäèòü ГЁГ§ ГЇГ*ìÿòè
                TMyData *mydata = new TMyData;
                mydata->FormHandle = this->Handle;
                mydata->Memo = this->Memo1;
 
                CreateThread(NULL, NULL, ThreadFunc, mydata, NULL, NULL);
        }
}
//---------------------------------------------------------------------------
 
// òåëî äîïîëГ*èòåëüГ*ûõ ïîòîêîâ
DWORD WINAPI ThreadFunc( LPVOID param)
{
        TMyData *mydata = (TMyData*)param;
 
        HANDLE FormHandle = mydata->FormHandle;
 
        // ïåðåäГ*ГҐГ¬ ГІГҐГЄГ±ГІ ГЁГ§ ïîòîêГ* Гў Memo;
        // ГЅГІГ® ìîæГ*Г® îñóùåñòâèòü ГЁГ§ îñГ*îâГ*îãî ïîòîêГ*,
        // äëÿ ýòîãî ïåðåäГ*ГҐГ¬ Гў îñГ*îâГ*îé ïîòîê (òî÷Г*ГҐГҐ îêîГ*Г*îé ïðîöåäóðå) ГіГЄГ*Г§Г*òåëü Г*Г* ГґГіГ*êöèþ, êîòîðГ*Гї Гў ñâîþ î÷åðåäü ГЁ äîáГ*ГўГЁГІ ГІГҐГЄГ±ГІ Гў Ìåìî
        for ( int i = 0; i < 4; i++ )
        {
                // ñîçäГ*ГҐГ¬ êîïèþ ýêçåìïëÿðГ* Г¤Г*Г*Г*ûõ ГЁ îïÿòü Г*ГіГ¦Г*Г® áóäåò ГҐГЈГ® ГіГ¤Г*ëÿòü ГЁГ§ äðóãîãî (îñГ*îâГ*îãî) ïîòîêГ*
                // ГўГ® èçáåæГ*Г*ГЁГҐ "delete mydata" (Г±Г¬. ГЄГ®Г*ГҐГ¶ ГґГіГ*êöèè)
                // ìîæГ*Г® áûëî ГЁ Г± ïîìîùüþ event'îâ Г°Г*çðåøèòü ГЅГІГі ïðîáëåìó
                TMyData *_mydata = new TMyData;
                memcpy(_mydata, mydata, sizeof(*mydata));
 
                // âûäåëÿåì ГЇГ*ìÿòü ïîä ГІГҐГЄГ±ГІ (ГҐВё ïîçæå Г*ГіГ¦Г*Г® áóäåò îñâîáîäèòü ГЁГ§ ГґГіГ*êöèè SyncFunc)
                // ôîðìèðóåì ГІГҐГЄГ±ГІ ГЁ îòïðГ*âëÿåì îêîГ*Г*îé ïðîöåäóðå Г*Г*ГёГҐ ñîîáùåГ*ГЁГҐ WM_USER+1,
                // ïðè îáðГ*áîòêå ýòîãî ñîîáùåГ*ГЁГї îêîГ*Г*Г*Гї ïðîöåäóðГ* äîëæГ*Г* áóäåò âûçâГ*ГІГј ГґГіГ*êöèþ SyncFunc, Г* ГІГ* Гў ñâîþ
                // î÷åðåäü äîëæГ*Г* äîáГ*ГўГЁГІГј ñòðîêó Гў Memo
                char *str = new char[64];
                sprintf(str, "Text %d from thread %d", i, GetCurrentThreadId());
                _mydata->Text = str;
                SendMessage(FormHandle, WM_USER+1, (WPARAM)SyncFunc, (LPARAM)_mydata);
        }
 
        // îñâîáîæäГ*ГҐГ¬ ïåðåäГ*Г*Г*ûé ýêçåìïëÿð Г¤Г*Г*Г*ûõ
        delete mydata;
 
        return 0;
}
 
// ГґГіГ*êöèÿ, ГіГЄГ*Г§Г*òåëü Г*Г* êîòîðóþ ìû ïåðåäГ*ГҐГ¬ îêîГ*Г*îé ïðîöåäóðå
// äëÿ òîãî, ÷òîáû ГІГ* ГҐВё âûçâГ*Г«Г* Гў îñГ*îâГ*îì ïîòîêå
void SyncFunc(LPVOID param)
{
        TMyData *mydata = (TMyData*)param;
        TMemo *Memo = mydata->Memo;
        char *Text = mydata->Text;
 
        // äîáГ*âëÿåì ñòðîêó Гў Memo
        Memo->Lines->Add(Text);
 
        // îñâîáîæäГ*ГҐГ¬ ГЇГ*ìÿòü, âûäåëåГ*Г*ГіГѕ äîïîëГ*èòåëüГ*ûì ïîòîêîì
        delete []Text;
        delete mydata;
}
 
// îêîГ*Г*Г*Гї ïðîöåäóðГ*
LRESULT CALLBACK MyWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        LRESULT ret = 0;
 
        switch (uMsg)
        {
                case WM_USER+1: // îáðГ*ГЎГ*òûâГ*ГҐГ¬ Г*Г*ГёГҐ ñîîáùåГ*ГЁГҐ
                {
                        void (*MyFunc)(LPVOID) = (void (*)(void*))wParam; // ГіГЄГ*Г§Г*òåëü Г*Г* ГґГіГ*êöèþ, êîòîðóþ Г*ГіГ¦Г*Г® âûçâГ*ГІГј
                        MyFunc((LPVOID)lParam); // âûçûâГ*ГҐГ¬ ГЅГІГі ГґГіГ*êöèþ
                        break;
                }
                default:
                {
                        ret = CallWindowProc(MyOldWndProc, hwnd, uMsg, wParam, lParam);
                }
        }
 
        return ret;
}
2
06.10.2013, 10:10
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.10.2013, 10:10

Ошибка доступа к памяти, ошибка компонентов .bpl
Использую в проекте библиотеку bass.dll. И при работе с ней у билдера часто возникают ошибки. Либо...

Ошибка доступа к памяти
Доброго времени суток! Возникла проблема. Есть класс СТРОКА. В нем перегруженные операторы &quot;-&quot;...

Телефонная книга. Ошибка доступа к памяти
Всем доброго дня! Есть задача написать телефонную книгу. Поиск в ней осуществляется через...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

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