Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> вопрос по CreateThread 
:(
    Опции темы
yngwie19
Дата 30.3.2009, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



всем привет. Как известно фукция CreateThread возвращает дескриптор созданного потока, но скажите зачем тогда нужен 6 -ой пераметр этой функции (идентификатор потока) Я думал. что это одно и тоже!
PM MAIL   Вверх
EvilsInterrupt
Дата 31.3.2009, 08:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 1
Всего: 9



yngwie19, 
Господин Рихтер так думает:
Цитата

Параметр pdwThreadlD 

Последний параметр функции CreateTbread — это адрес переменной типа DWORD, в которой функция возвращает идентификатор, приписанный системой новому пото ку. (Идентификаторы процессов и но'юков рассматривались в главе 4.) 

NOTE: 
В Windows 2000 и Windows NT 4 в этом параметре можно передавать NULL (обычно так и делается). Тем самым Вы сообщаете функции, что Вас не инте ресует идентификатор потока Ilo в Windows 95/98 это приведет к ошибке, так как функция попытается записать идентификатор потока no нулевому адресу, что недопустимо. И поток не будет создан. 

Такое несоответствие между операционными системами может создать разработчикам приложений массу проблем, Допустим, Вы пишете и тестируе те программу в Windows 2000 (которая создает поток, даже если Вы передаете NULL в pdwThreadID) Но вот Вы запускаете приложение в Windows 98, и фун кция CreateThread, естественно, дает ошибку. Вывод один: тщательно тестируй те свос приложение во всех операционных системах, в которых оно будет работать

PM MAIL WWW ICQ Jabber   Вверх
yngwie19
Дата 31.3.2009, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Я думаю, что по Windows 95/98 сейчас уже никто не работает. Значит мне впринципе этот параметр не нужен и Я могу смело ставить NULL, главное это дескриптор потока который возвращает эта функций так? 
PM MAIL   Вверх
Alca
Дата 31.3.2009, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Мой тебе совет: не используй CreateThread т.к. будут небольшие утечки памяти (если юзаешь CRT). Юзай _beginthreadex.

Добавлено через 1 минуту и 23 секунды
Цитата

Sample _beginthreadex

The following is a sample use of _beginthreadex. In this sample, an event is created and passed as an argument. The thread checks the event in a loop and when the event is signaled (by the main thread) the thread returns. Please read the _beginthreadex() and _endthreadex() documentation; this sample assumes you have and that you are familiar with it.
Код

#if !defined(_MT)
#error _beginthreadex requires a multithreaded C run-time library.
#endif

#define STRICT 1
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

#define Second (1000)

unsigned __stdcall Thread(void *ArgList) {
HANDLE hEvent = *((HANDLE*)ArgList);
while (WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0) {
    Sleep(Second>>2); // sleep for a quarter of a second
    cout << "Waiting for signal\n";
    }
cout << "Thread ending\n";
return 0;
}

int main(int argc, char *argv[], char *envp[]) {
    int ErrorNumber, DOSErrorNumber;
    unsigned ThreadId;
    HANDLE hThread, hEvent;

// Create a manual-reset nonsignaled unnamed event
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

hThread = (HANDLE)_beginthreadex(NULL, 0, Thread, &hEvent, 0, &ThreadId);
if (hThread == 0) {
    ErrorNumber = errno;
    DOSErrorNumber = _doserrno;
    cerr << "Begin thread error: " << strerror(ErrorNumber) << '\n';
    cerr << "Begin thread DOS error code: " << DOSErrorNumber << '\n';
    return 16;
    }
cout << "Thread begun\n";

Sleep(Second<<1); // wait 2 seconds
SetEvent(hEvent); // signal thread to end
int rv = WaitForSingleObject(hThread, Second<<3); // wait up to 8 seconds
cout << "Thread wait rv " << rv << '\n';
CloseHandle(hEvent);
CloseHandle(hThread);

return 0;
}

Microsoft Knowledge Base article 132078 ("How to Use _beginthreadex() and _endthreadex()")

The KB article 132078 ("How to Use _beginthreadex() and _endthreadex()") seems to have been archived, so I will summarize here what it says. It essentially says that it is better to use _beginthreadex() and _endthreadex() and it has a sample program. My sample above is an improved version of the sample in the KB article.

Use of the Win32 APIs CreateThread() and EndThread() directly is incompatible with the C Runtime (CRT) Library. In particular, use of CreateThread() and EndThread() directly can cause loss of memory that the CRT allocates. Instead, we must use either _beginthread() and _endthread() or _beginthreadex() and _endthreadex().

The advantage of _beginthreadex() compared to _beginthread() is that _beginthreadex() provides more control and is safer. For example, with _beginthreadex(), you can:
use security information
create the thread suspended initially
get the thread identifier of the thread
use the thread handle after the thread completes, allowing use of the the synchronization APIs (as above) for the thread

The advantage of _endthreadex() compared to _endthread() is that _endthreadex() is more flexible.



--------------------
PM WWW ICQ Skype Jabber   Вверх
yngwie19
Дата 31.3.2009, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Цитата(Alca @  31.3.2009,  10:44 Найти цитируемый пост)
не используй CreateThread т.к. будут небольшие утечки памяти 

В чем выражаются эти утечки памяти.
Я пока что тока начал разбираться с потоками поэтому в книге приводится именно эта функция. 
А что насчет 
Цитата(yngwie19 @  31.3.2009,  10:36 Найти цитируемый пост)
Значит мне впринципе этот параметр не нужен и Я могу смело ставить NULL, главное это дескриптор потока который возвращает эта функций так?  



Это сообщение отредактировал(а) yngwie19 - 31.3.2009, 17:31
PM MAIL   Вверх
Alca
Дата 31.3.2009, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

Значит мне впринципе этот параметр не нужен и Я могу смело ставить NULL, главное это дескриптор потока который возвращает эта функций так?  

 smile

Добавлено через 38 секунд
Ставь NULL

Добавлено через 1 минуту и 30 секунд
Цитата

В чем выражаются эти утечки памяти.


Цитата

loss of memory that the CRT allocates


Добавлено через 2 минуты и 15 секунд
И внизу страницы глянь - там есть ссылки для тебя.


--------------------
PM WWW ICQ Skype Jabber   Вверх
yngwie19
Дата 31.3.2009, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Alca, Спасибо. Подскажи подалуйста допустим такой участок кода
Код


DWORD WINAPI Thread(LPVOID nCnt)
{

        return 0;
}

int WINAPI WinMain(......)
..........
int nPar = 10;
CreateThread(NULL,0,Thread,(LPVOID)nPar,0,NULL);
..........

Вопрос:
1) При передаче парамметра nPar в функцию Thread(), он передается как указатель ? т.е 
2) При передаче этого параметра в функции CreateThread() мы сначала его преобразовываем в указатель что-ли? или как
PM MAIL   Вверх
Alca
Дата 31.3.2009, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Код

#include <windows.h>
#include <iostream.h>

volatile int n;

DWORD WINAPI Add(LPVOID iNum)
{
  cout << "Thread is started." << endl;
  n += (int)iNum;
  cout << "Thread is finished." << endl;

  return 0;
}

int main()
{
  int  inc = 10;
  HANDLE  hThread;
  DWORD  IDThread;

  cout << "n = " << n << endl;
  // запускаем поток Add
  hThread = CreateThread(NULL, 0, Add, (void*)inc, 0, &IDThread);
  if (hThread == NULL)
    return GetLastError();

  // ждем, пока поток Add закончит работу
  WaitForSingleObject(hThread, INFINITE);
  // закрываем дескриптор потока Add
  CloseHandle(hThread);

  cout << "n = " << n << endl;

  return 0;
}


Добавлено через 5 минут и 22 секунды
Цитата

1) При передаче парамметра nPar в функцию Thread(), он передается как указатель ? т.е 
2) При передаче этого параметра в функции CreateThread() мы сначала его преобразовываем в указатель что-ли? или как

типа да

Добавлено через 10 минут и 45 секунд
Можно еще так:
Код

hThread = CreateThread(NULL, 0, Add, &inc, 0, &IDThread);



--------------------
PM WWW ICQ Skype Jabber   Вверх
yngwie19
Дата 31.3.2009, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Цитата(Alca @  31.3.2009,  21:14 Найти цитируемый пост)
Можно еще так:

код C++
1:

hThread = CreateThread(NULL, 0, Add, &inc, 0, &IDThread);


дык здесь ты передаешь &inc как указатель типа int, а функция принимает void*. Здесь привести в void* случайно не надо?
PM MAIL   Вверх
Alca
Дата 31.3.2009, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Скомпилилось без ворнингов.

Добавлено @ 21:36
Creating Threads

Добавлено @ 21:38
Код

HANDLE WINAPI CreateThread(
  __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in       SIZE_T dwStackSize,
  __in       LPTHREAD_START_ROUTINE lpStartAddress,
  __in_opt   LPVOID lpParameter,
  __in       DWORD dwCreationFlags,
  __out_opt  LPDWORD lpThreadId
);

lpParameter [in, optional] 

A pointer to a variable to be passed to the thread.


Это сообщение отредактировал(а) Alca - 31.3.2009, 21:39


--------------------
PM WWW ICQ Skype Jabber   Вверх
yngwie19
Дата 31.3.2009, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Alca, Спасибо, все же мне не очень понятно как можно переменную (в нашем случае int) привести в указателю.
PM MAIL   Вверх
Alca
Дата 31.3.2009, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Вот так:
Код

(void*)inc


Добавлено через 30 секунд
или так:
Код

&inc



--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 31.3.2009, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



[quote=Alca, 31.3.2009,  21:45, post1829523]Вот так:

(void*)inc
или так:
&inc

Эй, Alca, вы чего?

PM MAIL ICQ   Вверх
Rififi
Дата 31.3.2009, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 2
Всего: 36



yngwie19, 
дык здесь ты передаешь &inc как указатель типа int, а функция принимает void*. Здесь привести в void* случайно не надо? 
не надо. указатель на void "паглащает" все другие типы указателей.
PM MAIL   Вверх
yngwie19
Дата 31.3.2009, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Цитата(Anikmar @  31.3.2009,  21:57 Найти цитируемый пост)
Эй, Alca, вы чего?
 что-то не так?
Дак что получается была переменная - стал указатель и никаких проблем?

PM MAIL   Вверх
Rififi
Дата 31.3.2009, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 2
Всего: 36



yngwie19, 
это же C++ - "делай шо хочешь"
соответственно, если этот указатель превратить обратно в переменную целого типа, то проблем никаких и не будет.
PM MAIL   Вверх
Anikmar
Дата 31.3.2009, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(yngwie19 @  31.3.2009,  22:16 Найти цитируемый пост)
 что-то не так?
Дак что получается была переменная - стал указатель и никаких проблем?


int и указатель не одно и тоже. Никто не гарантирует, что они будут одинакового размера. Передавать int в указателе считаю неправильным.
PM MAIL ICQ   Вверх
Alca
Дата 31.3.2009, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

Передавать int в указателе считаю неправильным.

Тогда по ссылке


--------------------
PM WWW ICQ Skype Jabber   Вверх
Anikmar
Дата 31.3.2009, 23:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Правильно будет передавать только адрес.

Функция требует void* - значит ей надо передать любой указатель. Нельзя помещать в указатель другую информацию.
PM MAIL ICQ   Вверх
GoldFinch
Дата 1.4.2009, 08:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Цитата(Anikmar @  1.4.2009,  00:04 Найти цитируемый пост)
int и указатель не одно и тоже. Никто не гарантирует, что они будут одинакового размера. Передавать int в указателе считаю неправильным. 

Я бы понял если бы речь шла о кроссплатформенности, и то, размер указателя всегда больше или равен размеру int
Но речь идет о системной функции win32, и тут рассуждения о размере int и размере указателя совершенно бессмысленны, т.к. туда надо передавать только 4-байтовые значения, как int так и указателей

Система не различает, указатели или значения передаются callback'ам, т.к. они просто копируются.
Более того, кроме C++ программы под win32 можно писать и на других языках программирования, например на *asm, так вот учитывая правила написания программ под win32 вообще, безотносительно языка программирования, в CreateThread параметром потоку можно передавать любые 4 байта.

Это сообщение отредактировал(а) GoldFinch - 1.4.2009, 08:53
PM MAIL ICQ   Вверх
Anikmar
Дата 1.4.2009, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GoldFinch @  1.4.2009,  08:43 Найти цитируемый пост)
Я бы понял если бы речь шла о кроссплатформенности, и то, размер указателя всегда больше или равен размеру int
Но речь идет о системной функции win32, и тут рассуждения о размере int и размере указателя совершенно бессмысленны, т.к. туда надо передавать только 4-байтовые значения, как int так и указателей

Система не различает, указатели или значения передаются callback'ам, т.к. они просто копируются.
Более того, кроме C++ программы под win32 можно писать и на других языках программирования, например на *asm, так вот учитывая правила написания программ под win32 вообще, безотносительно языка программирования, в CreateThread параметром потоку можно передавать любые 4 байта.


Я имею в виду не конкретно данную ситуацию, а подход вцелом. 
ИМХО. Если требуется указатель - надо передавать указатель, а не использовать левые преобразования

PM MAIL ICQ   Вверх
GoldFinch
Дата 1.4.2009, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Anikmar, а при чем тут подход в целом? тут вполне конкретный случай
и указатель там не требуется, это в заголовочных файлах С++ написано что указатель, а в заголовочных файлах для других языков, там не указатель
PM MAIL ICQ   Вверх
Anikmar
Дата 1.4.2009, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GoldFinch @  1.4.2009,  11:02 Найти цитируемый пост)
Anikmar, а при чем тут подход в целом? тут вполне конкретный случай
и указатель там не требуется, это в заголовочных файлах С++ написано что указатель, а в заголовочных файлах для других языков, там не указатель 


ИМХО
Есть интерфейс. Интерфейсу требуется указатель. Вот и надо его передать. Если рассматривать частные случаи, то С++ позволит сделать практически все. Я за общий подход, поэтому за то, чтобы не передавать в указателях целые параметры. И рассматривать заголовочные файлы других языков - это не разговор. Что за функция конкретно вызывается из exe, скомпилированного на С++ и какая из exe других языков заранее мы знать не можем. Конкретно в данном случае - известная функция, всем известно что она делает и я полностью согласен, что никакого вреда в этом случае не будет. Но лично я придерживаюсь другого стиля.
Опять-таки ИМХО


PM MAIL ICQ   Вверх
GoldFinch
Дата 1.4.2009, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Цитата(Anikmar @  1.4.2009,  14:49 Найти цитируемый пост)
поэтому за то, чтобы не передавать в указателях целые параметры. 

там еще float можно передать
Цитата(Anikmar @  1.4.2009,  14:49 Найти цитируемый пост)
Что за функция конкретно вызывается из exe, скомпилированного на С++ и какая из exe других языков заранее мы знать не можем. Конкретно в данном случае - известная функция

вызов-то ее размещен в .exe, а сама-то функция во внешней .dll
кроме того, в ее интерфейсе указано соглашение вызова, stdcall, так вот согласно соглашению вызова stdcall разницы между указателем, целочисленным 4-байтовым значением, или любым другим 4-байтовым значением нет. 
и язык программирования, раз указано конкретное соглашение вызова, тут совершенно ни при чем.
PM MAIL ICQ   Вверх
GremlinProg
Дата 1.4.2009, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



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

ради справедливости, можешь поставить перед вызовом функции 
Код

assert( sizeof(int) <= sizeof(void*) )

и все проблемы решатся:
и совместимость не нарушена
и не нужно плодить лишний код

ИМХО, такого рода перестраховки - просто тараканы, о которых ты забудешь, как только начнешь задумываться о том, как сильно они сказываются на твоем КПД

Добавлено через 9 минут и 30 секунд
GoldFinch, слишком много ненужных подробностей,
и stdcall тут ни при чем: выравнивание стека параметров не равно размеру элемента, это всего лишь лишь его кратность


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 2.4.2009, 08:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  1.4.2009,  15:17 Найти цитируемый пост)
Anikmar, все верно, пока речь не идет о производительности
так можно и не дойти до решения основной задачи,
а даже если дойти, то код уже будет неэффективным


Сначала обсуждали конкретный пример, теперь речь о производительности. В данном конкретном случае никакого выигрыша по производительности заметно не будет.

Цитата(GoldFinch @  1.4.2009,  15:05 Найти цитируемый пост)
кроме того, в ее интерфейсе указано соглашение вызова, stdcall, так вот согласно соглашению вызова stdcall разницы между указателем, целочисленным 4-байтовым значением, или любым другим 4-байтовым значением нет.

Закладывать в свой код предположение о размере указателя и целого числа как 4 байта я и считаю отступлением от общего нормального подхода. Сколько байт точно вешать знает только sizeof. Если говорить о stdcall то данный модификатор лишь объявляет соглашение о вызове функции в совместимом с win32 формате. Никаких 4, а также 5, 6 или 8 байт он не предусматривает.
Соглашение лишь о порядке следования параметров и о способе передаче параметров по значению:
MSDN:
Цитата

Microsoft Specific 

The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype.

return-type __stdcall function-name[(argument-list)] Remarks 
The following list shows the implementation of this calling convention.

Element  Implementation  
Argument-passing order
 Right to left.
 
Argument-passing convention
 By value, unless a pointer or reference type is passed.


Цитата(GremlinProg @  1.4.2009,  15:17 Найти цитируемый пост)
assert( sizeof(int) <= sizeof(void*) )

ИМХО. Данная вещь хороша при отладке. А закладывать в код вероятность вылета из-за кривого программирования - тут, конечно, дело вкуса, но не проще ли предусмотреть нормальную работу в любом варианте - тем более здесь не требуется особых наворотов.

Цитата(GremlinProg @  1.4.2009,  15:17 Найти цитируемый пост)
ИМХО, такого рода перестраховки - просто тараканы, о которых ты забудешь, как только начнешь задумываться о том, как сильно они сказываются на твоем КПД

Это не перестраховка, а просто мое мнение (и не только мое, кстати), что конструкций вида
Код

int a;
void *p;
...
p = (void*)a;


Нужно избегать. 

ИМХО.
PM MAIL ICQ   Вверх
GoldFinch
Дата 2.4.2009, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Anikmar, будет выигрыш не только по производительности, но и по безопасности, не надо обеспечивать время жизни указателя на все время жизни потока
PM MAIL ICQ   Вверх
GoldFinch
Дата 2.4.2009, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Цитата(Anikmar @  2.4.2009,  09:43 Найти цитируемый пост)
Закладывать в свой код предположение о размере указателя и целого числа как 4 байта я и считаю отступлением от общего нормального подхода. Сколько байт точно вешать знает только sizeof.

это в кроссплатформенном С\С++ это нормальный подход
а при работе с конкретной платформой, всегда надо знать и учитывать численные характеристики платформы

Цитата(Anikmar @  2.4.2009,  09:43 Найти цитируемый пост)
Соглашение лишь о порядке следования параметров и о способе передаче параметров по значению:

там в msdn написано далеко не все

более точное описание условий для вызова системных апи выглядит так
Цитата

следует соблюдать следующие условия для вызова системного апи(модель вызова не имеет значения, stdcall etc.):
> Стек выравнен на 4 байта.
> Страница стека доступна для чтения, записи и может быть расширена вниз при переполнении стека.
> Границы стека определены в TIB.
> Сброшен бит DF в регистре флагов.
> Изменяются регистры Eax, Ecx, Edx, Esp, EFlags.
> Валидные селекторы.

© Clerk (wasm.ru)

PM MAIL ICQ   Вверх
Anikmar
Дата 2.4.2009, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GoldFinch @  2.4.2009,  10:07 Найти цитируемый пост)
там в msdn написано далеко не все

более точное описание условий для вызова системных апи выглядит так

Я привел только то, что касается непосредственно темы обсуждения.

У меня сложилось впечатление, что вы большой приверенженец ассемблера и из-за этого достаточно яростно отстаиваете подходы, которые часто применяют именно ASM-программеры. Касаемо текущего обсуждения общий фон такой: Да, это вроде как не совсем правильно, но в конкретном этом случае можно. Я же изначально сказал, что в общем (а не конкретном) подходе так делать не рекомендуют, и я сам так не делаю. Хотя бы из-за того, что код для виндов также должен переносится в более свежие версии и нужно делать максимально меньше подозрительных крякозябр. В этом случае ничего не произойдет, зато в другом случае можно потратить неделю на поиск ошибки. Легче приучить себя изначально делать правильно - и все будет ок.

Цитата(GoldFinch @  2.4.2009,  10:07 Найти цитируемый пост)
это в кроссплатформенном С\С++ это нормальный подход
а при работе с конкретной платформой, всегда надо знать и учитывать численные характеристики платформы


Знать, учитывать и использовать - совершенно разные вещи. Я к кросс-платформенности отношусь с большим скепсисом. ИМХО нельзя написать по-настоящему хорошее, удобное, оптимизированное кросс-платформенное приложение. В данном же конкретном случае это не к кроссплатформенности относится, а к стилю программирования на C++. К преобразованию типов надо всегда подходить очень ответственно.

Цитата(GoldFinch @  2.4.2009,  09:35 Найти цитируемый пост)
Anikmar, будет выигрыш не только по производительности, но и по безопасности, не надо обеспечивать время жизни указателя на все время жизни потока 

Производительность оставим в покое. А вот по поводу обеспечения времени жизни - все зависит от конкретной задачи. Если создаваемому потоку достаточно парметра int это одно, если надо чего-то больше, то все равно надо обеспечивать необходимое время жизни. И писать в одном случае так, а в другом этак - дело, конечно вкуса, но не мой стиль точно.
ИМХО, однако.

PM MAIL ICQ   Вверх
GoldFinch
Дата 2.4.2009, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Anikmar, да при чем тут асм? я еще когда кодил только на турбопаскале\делфи уже знал сколько байт какая переменная занимает
а вы подозреваю это все никак не можете запомнить вот и говорите про sizeof

sizeof для простых типов данных нужен если вам надо менять строчку
  typedef float MyData;
на
  typedef double MyData;
чтобы не менять везде *4 на *8

а если вы и так знаете сколько байт занимает тип, и не собираетесь менять этот тип на другой, можно смело юзать константу
PM MAIL ICQ   Вверх
Anikmar
Дата 2.4.2009, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GoldFinch @  2.4.2009,  15:53 Найти цитируемый пост)
 я еще когда кодил только на турбопаскале\делфи уже знал сколько байт какая переменная занимает

И каков же размер int в TurboC?

Цитата(GoldFinch @  2.4.2009,  15:53 Найти цитируемый пост)
sizeof для простых типов данных нужен если вам надо менять строчку
  typedef float MyData;
на
  typedef double MyData;
чтобы не менять везде *4 на *8

sizeof нужен для того, чтобы свой код сделать правильным и не зависимым от конкретного компилятора (даже не платформы).

Цитата(GoldFinch @  2.4.2009,  15:53 Найти цитируемый пост)
а если вы и так знаете сколько байт занимает тип, и не собираетесь менять этот тип на другой, можно смело юзать константу

Если вы считаете этот подход правильным - вперед с песнями и барабаном  smile 

Другой момент, правильно написанный код с использование sizeof, при смене в компиляторе размера базового типа, вообще менять не придется. Нигде. Был int 16, затем 32, сейчас 64 будет - код будет компилироваться и работать.

Цитата(GoldFinch @  2.4.2009,  15:53 Найти цитируемый пост)
а вы подозреваю это все никак не можете запомнить вот и говорите про sizeof

Что вы. Я даже размер байта не знаю  smile.

Это сообщение отредактировал(а) Anikmar - 2.4.2009, 16:04
PM MAIL ICQ   Вверх
GremlinProg
Дата 2.4.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Anikmar @  2.4.2009,  10:43 Найти цитируемый пост)
Сначала обсуждали конкретный пример, теперь речь о производительности. В данном конкретном случае никакого выигрыша по производительности заметно не будет.

на одну операцию, конечно не будет, я в общем-то пекусь не столько о производительности программы, сколько о производительности программиста

Цитата(Anikmar @  2.4.2009,  10:43 Найти цитируемый пост)

Цитата(GremlinProg @  1.4.2009,  17:17 Найти цитируемый пост)
assert( sizeof(int) <= sizeof(void*) )

ИМХО. Данная вещь хороша при отладке. А закладывать в код вероятность вылета из-за кривого программирования - тут, конечно, дело вкуса, но не проще ли предусмотреть нормальную работу в любом варианте - тем более здесь не требуется особых наворотов.

не понял, а при чем тут криворукость?

assert дает простой способ решать конфликты в отладочной версии,
суть не в том, что он пропускается в релизе, а в том, что в релизе его можно переопределить на нормальный выход из программы, с соответствующим уведомлением пользователя, мол "версия программы несовместима с платформой, обращайтесь по такому-то адресу, к разработчику"

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

ничего страшного в этом нет, это простой способ экономить тебе твое же время, не более

практически в любой программе существует вероятность незапланированного вылета, к примеру: файл, который является основным источником информации, на данный момент не читается (кто-то его открыл)
что делать?
1. можно подождать пока его не закроют (многопоточность, система слежения и т.п.)
2. можно предложить пользователю отменить, приостановить текущую операцию (комбинац. логика, куча проверок, условий и т.п.)
3. а можно просто остановить программу (единый механизм обработки критических ошибок и обратной связи)

только третий вариант дает тебе возможность не городить огород и экономит время (дает возможность потратить его на основной функционал программы)

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

GoldFinch, Anikmar, чего делите-то, не пойму
две крайности одной формальности ))


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 2.4.2009, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  2.4.2009,  16:35 Найти цитируемый пост)
не понял, а при чем тут криворукость?

assert дает простой способ решать конфликты в отладочной версии,
суть не в том, что он пропускается в релизе, а в том, что в релизе его можно переопределить на нормальный выход из программы, с соответствующим уведомлением пользователя, мол "версия программы несовместима с платформой, обращайтесь по такому-то адресу, к разработчику"


Я не сказал криворукость. Я сказал "Кривое программирование". Руки, которые это делают - могут быть золотыми.  smile 
Именно про отладку я и сказал. Конкретно в приведенном примере проверяется  не платформа, а совпадение необходимых размеров для преобразования типа. Это я и назвал кривым программированием. Вместо того, чтобы вводить дополнительную проверку на то, что размеры нормально совпадут - просто не рисковать и делать гарантированно правильно. Это даже не платформо-зависимость, а компилеро-ззависимость.

Цитата(GremlinProg @  2.4.2009,  16:35 Найти цитируемый пост)
ничего страшного в этом нет, это простой способ экономить тебе твое же время, не более

И я про это. Никаких дополнительных затрат времени особо не будет - сразу сделать нормально. А потратить чужое время на написание гневного письма, а затем свое - на ответ (а если гневных писем будет много?  smile ) - вот и вспомнится экономия  smile 
ИМХО: платформу вообще надо проверять при инсталляции. "Извините - данная версия программы не совместима с вашим ковриком для мыши" что-нибудь такое.

Цитата(GremlinProg @  2.4.2009,  16:35 Найти цитируемый пост)
практически в любой программе существует вероятность незапланированного вылета, к примеру: файл, который является основным источником информации, на данный момент не читается (кто-то его открыл)
что делать?
1. можно подождать пока его не закроют (многопоточность, система слежения и т.п.)
2. можно предложить пользователю отменить, приостановить текущую операцию (комбинац. логика, куча проверок, условий и т.п.)
3. а можно просто остановить программу (единый механизм обработки критических ошибок и обратной связи)

только третий вариант дает тебе возможность не городить огород и экономит время (дает возможность потратить его на основной функционал программы)

Так вот откуда надписи типа "Произошла внутренняя ошибка программы. Все данный будут потеряны. Если ошибка повторится свяжитесь с разработчиком". В ведро такой софт. ИМХО. Надо к таким фразам издевательскую надпись добавлять "Видите-ли, программисту было лень городить огород- так как основное время он потратил на другой функционал, но он с удовольствием выслушает ваши претензии"  smile 

Цитата(GremlinProg @  2.4.2009,  16:35 Найти цитируемый пост)
GoldFinch, Anikmar, чего делите-то, не пойму
две крайности одной формальности )) 


Да ничего мы не делим. У каждого свой подход и свой взгляд на жизнь. Я чистой воды прикладник, писал вещи узкоспециализированные и заказные. Напрямую общался с конкретными пользователями и очень хорошо знаю претензии типа "Эту кнопку надо по-другому назвать, а  вот это поставить в левый нижний угол". Уровень моих пользователей - это при слове файл, они сразу думали про пластиковый конвертик. И вариант "напишите разработчику" у меня не прокатывает никак. Первый мой принцип - максимальная дуракоустойчивость".

PM MAIL ICQ   Вверх
GremlinProg
Дата 2.4.2009, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Anikmar @  2.4.2009,  19:07 Найти цитируемый пост)
Конкретно в приведенном примере проверяется  не платформа, а совпадение необходимых размеров для преобразования типа. Это я и назвал кривым программированием.

ну, это как посмотреть, где ты встречал платформу, которая разницу между размерами двух своих типов данных декларирует по-разному?
это просто логическое следствие
я в таком случае не вижу причины называть здесь что-то кривым
на разницу между отладкой и релизом, я ведь тоже внимание обратил:
Цитата(GremlinProg @  2.4.2009,  18:35 Найти цитируемый пост)
суть не в том, что он пропускается в релизе, а в том, что в релизе его можно переопределить на нормальный выход из программы

Цитата(Anikmar @  2.4.2009,  19:07 Найти цитируемый пост)
И я про это. Никаких дополнительных затрат времени особо не будет - сразу сделать нормально. А потратить чужое время на написание гневного письма...

сразу нормально - это только если задачка не сложная, без ветвлений
а конфликты с пользователями по-хорошему должны решать "манагеры по работе с клиентами", они для этого и нужны, если ты совмещаешь эти должности, требуй прибавки к зарплате, прибавили - терпи сам выбрал, а нет - уходи, не понимаю, зачем тратить нервы впустую (клиенты ведь разные бывают, могут любой мелочи придраться, не наше это дело, вникать в их "критические дни")

Цитата(Anikmar @  2.4.2009,  19:07 Найти цитируемый пост)
Так вот откуда надписи типа "Произошла внутренняя ошибка программы. Все данный будут потеряны. Если ошибка повторится свяжитесь с разработчиком". В ведро такой софт. ИМХО. Надо к таким фразам издевательскую надпись добавлять "Видите-ли, программисту было лень городить огород- так как основное время он потратил на другой функционал, но он с удовольствием выслушает ваши претензии"

какие данные? если софт в принципе не для этой платформы, какие он там данные-то успел навоять?
ну, можно поздравить его, коли так, мол мы даже не подозревали о таких скрытых вохможностях нашей программы, такую поддержку мы намечали только в n-ой версии продукта


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Anikmar
Дата 2.4.2009, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 59



Цитата(GremlinProg @  2.4.2009,  18:07 Найти цитируемый пост)
ну, это как посмотреть, где ты встречал платформу, которая разницу между размерами двух своих типов данных декларирует по-разному?
это просто логическое следствие

Ну вот, завел вас похоже.  smile  Объясню кривость такого подхода: Совместимость платформ проверяется на этапе инсталяции, но никак не при запуске основного софта. Т.е. идиот пользователь (ну они же все идиоты - к менеджерам их, пусть там разбираются) сидит и развлекается созерцанием инсталяции, затем жамкает кнопку "Запустить" (образно), а ему вежливый ответ: "видишь ли дурачок, у тебя не та платформа".
Опять таки к конкретно этому примеру: ну никак не должен софт зависеть от разницы в размерах int и указателя - хоть тресни. Останусь при своем ИМХО и не буду больше на эту тему спорить.

Цитата(GremlinProg @  2.4.2009,  18:07 Найти цитируемый пост)
сразу нормально - это только если задачка не сложная, без ветвлений

Каким образом ветвления влияют на аккуратность в преобразованиях и соблюдение чистоты кода? Напротив, чем сложнее задача, тем лучше придерживаться одного стиля.

Цитата(GremlinProg @  2.4.2009,  18:07 Найти цитируемый пост)
какие данные? если софт в принципе не для этой платформы, какие он там данные-то успел навоять?

Если такая проверка перед запуском - то конечно не успеет еще ничего наваять - кроме инсталяции самой программы, но об этом я уже написал. А так я такую фразу привел не касаемо кобсуждаемой ситуации, а касаемо к вашей точке зрения - пользователь это к менеджерам, интерфейс - попозже, главное функционал. Сколько людей, столько мнений.

Цитата(GremlinProg @  2.4.2009,  18:07 Найти цитируемый пост)
если ты совмещаешь эти должности, требуй прибавки к зарплате, прибавили - терпи сам выбрал, а нет - уходи, не понимаю, зачем тратить нервы впустую

Сам во всех ипостасях - очень просто так как фрилансер.
PM MAIL ICQ   Вверх
Dem_max
Дата 3.4.2009, 06:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



Согласен с  Anikmar, 
для переносимости кода необходимо использовать sizeof() там где это нужно. 
Для тех кто в "танке" и не хочет выходить от туда почитайте хотябы эту статью
20 ловушек переноса Си++ - кода на 64-битную платформу


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
GoldFinch
Дата 3.4.2009, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Dem_max, а при чем тут х64 ? там чтоли sizeof(int)!=sizeof(void*) ?
PM MAIL ICQ   Вверх
Dem_max
Дата 3.4.2009, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



Цитата

а при чем тут х64

да x64 тут особо не причем, но статья хорошая. 
Цитата

 sizeof(int)!=sizeof(void*) 

для некоторых платформ да.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1001 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.