Тут размещают свои топики новички в С/С++.

Тема в разделе "LANGS.C", создана пользователем nitrotoluol, 4 мар 2007.

  1. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    кстати при использовании CreateThread можно использовать небезопасные функции как пишет Рихтер такие функции проверяют на NULL элемент в массиве tls и если это так выделяют нужную память для безопасной работы а при завершении такого потока DLL получает DLL_THREAD_DETACH и не возникает проблем с утечкой памяти главное не гасить поток через TerminateThread :))
    а то память выделенная для стека потока не освободится и плюс к тому же утечки выделенные для блока tiddata :)

     
  2. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    если grep'ом пройтись по папке с исходниками CRT в поисках вызовов _getptd сразу видно небезопасные функции

    Код (Text):
    1. _getptd
    2. _getptd
    3. _getptd
    4. _getptd
    5. C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\crt\src\crtlib.c
    6. _getptd
    7. C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\crt\src\ctype.c
    8. _getptd
    9. C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\crt\src\lconv.c
    10. _getptd
    11. _getptd
    12. C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\crt\src\strftime.c
    13. _getptd
    14. _getptd
    15. C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\crt\src\wcsftime.c
    16. _getptd
    17. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\intel\_sampld_.def
    18. _getptd
    19. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\intel\_sample_.def
    20. _getptd
    21. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\asctime.c
    22. _getptd
    23. _getptd
    24. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\crtlib.c
    25. _getptd
    26. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\ctype.c
    27. _getptd
    28. _getptd
    29. _getptd
    30. _getptd
    31. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\dosmap.c
    32. _getptd
    33. _getptd
    34. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\fcvt.c
    35. _getptd
    36. _getptd
    37. _getptd
    38. _getptd
    39. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\getqloc.c
    40. _getptd
    41. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\gmtime.c
    42. _getptd
    43. _getptd
    44. _getptd
    45. _getptd
    46. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\initctyp.c
    47. _getptd
    48. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\lconv.c
    49. _getptd
    50. _getptd
    51. _getptd
    52. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\mbctype.c
    53. _getptd
    54. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\mbstok.c
    55. _getptd
    56. _getptd
    57. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\mtdll.h
    58. _getptd
    59. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\putch.c
    60. _getptd
    61. _getptd
    62. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\rand.c
    63. _getptd
    64. _getptd
    65. _getptd
    66. _getptd
    67. _getptd
    68. _getptd
    69. _getptd
    70. _getptd
    71. _getptd
    72. _getptd
    73. _getptd
    74. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\setlocal.c
    75. _getptd
    76. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\setlocal.h
    77. _getptd
    78. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\strerror.c
    79. _getptd
    80. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\strtok.c
    81. _getptd
    82. _getptd
    83. _getptd
    84. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\thread.c
    85. _getptd
    86. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\tidprint.c
    87. _getptd
    88. _getptd
    89. _getptd
    90. _getptd
    91. _getptd
    92. _getptd
    93. _getptd
    94. _getptd
    95. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\tidtable.c
    96. _getptd
    97. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\tmpfile.c
    98. _getptd
    99. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\wcstok.c
    100. _getptd
    101. _getptd
    102. _getptd
    103. _getptd
    104. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\winsig.c
    105. _getptd
    106. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\winxfltr.c
    107. _getptd
    108. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\write.c
    109. _getptd
    110. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\wsetloca.c
    111. _getptd
    112. C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\_strerr.c
    вот из исходников пример что происходит если поток был создан через CreateThread
    и вызвал небезопасную функцию например strtok я прокомментил
    самые интересные места

    Код (Text):
    1. char * __cdecl strtok (
    2.         char * string,
    3.         const char * control
    4.         )
    5. {
    6.         /*
    7.          * skip ...
    8.          */
    9.        
    10.         /*
    11.          * в самом начале каждой небезопасной функции идет вызов _getptd
    12.          * чтоб получить указатель на структуру _ptiddata
    13.          */
    14.         _ptiddata ptd = _getptd();
    15.  
    16.         /*
    17.          * skip ...
    18.          */
    19.  
    20. }
    21.  
    22.  
    23. ////////////////////////////////////////////////////////////////////////
    24. _ptiddata __cdecl _getptd (
    25.         void
    26.         )
    27. {
    28.         /*
    29.          * это только враппер который вызывает _getptd_noexit
    30.          */
    31.         _ptiddata ptd = _getptd_noexit();
    32.         if (!ptd) {
    33.             _amsg_exit(_RT_THREAD); /* write message and die */
    34.         }
    35.         return ptd;
    36. }
    37.  
    38.  
    39. ////////////////////////////////////////////////////////////////////////
    40. _ptiddata __cdecl _getptd_noexit (
    41.         void
    42.         )
    43. {
    44.     _ptiddata ptd;
    45.     DWORD   TL_LastError;
    46.  
    47.     TL_LastError = GetLastError();
    48.  
    49. #ifdef _M_IX86
    50.  
    51.     /*
    52.      * Initialize FlsGetValue function pointer in TLS by calling __set_flsgetvalue()
    53.      */
    54.     /*
    55.      * проверка сопоставлен ли с потоком блок _ptiddata
    56.      * если не сопоставлен выделяем память и инициализируем блок
    57.      */
    58.     if ( (ptd = (__set_flsgetvalue())(__flsindex)) == NULL ) {
    59. #else  /* _M_IX86 */
    60.     if ( (ptd = FLS_GETVALUE(__flsindex)) == NULL ) {
    61. #endif  /* _M_IX86 */
    62.         /*
    63.          * no per-thread data structure for this thread. try to create
    64.          * one.
    65.          */
    66. #ifdef _DEBUG
    67.         extern void * __cdecl _calloc_dbg_impl(size_t, size_t, int, const char *, int, int *);
    68.         if ((ptd = _calloc_dbg_impl(1, sizeof(struct _tiddata), _CRT_BLOCK, __FILE__, __LINE__, NULL)) != NULL) {
    69. #else  /* _DEBUG */
    70.         /*
    71.          * выделем память под структуру _ptiddata
    72.          *
    73.          */
    74.         if ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL) {
    75. #endif  /* _DEBUG */
    76.  
    77.             if (FLS_SETVALUE(__flsindex, (LPVOID)ptd) ) {
    78.  
    79.                 /*
    80.                  * Initialize of per-thread data
    81.                  */
    82.                  /*
    83.                   * инициализация
    84.                   */
    85.                 _initptd(ptd,NULL);
    86.                
    87.                 /*
    88.                  * записываем id треда
    89.                  * все таким образом если мы запустили поток через CreateThread
    90.                  * и вызвали скажем strtok все будет нормально небезопасная функция
    91.                  * проверив что блок не был выделен создает его инициализирует
    92.                  * и сопоставляет с тредом вызвавшим ее получается в потоках
    93.                  * созданных CreateThread это безопасно освободится он когда
    94.                  * функция потока вернет управление родительская функция вызовет ExitThread
    95.                  * DLL получит сообщение DLL_THREAD_DETACH и освободит память
    96.                  * если поток прибивается через TerminateThread будут утечки
    97.                  * так как DLL не получит DLL_THREAD_DETACH и память из под
    98.                  * стека потока тоже не освобождается что вдвойне плохо
    99.                  */
    100.                 ptd->_tid = GetCurrentThreadId();
    101.                 ptd->_thandle = (uintptr_t)(-1);
    102.             }
    103.             else {
    104.  
    105.                 /*
    106.                  * Return NULL to indicate failure
    107.                  */
    108.  
    109.                 _free_crt(ptd);
    110.                 ptd = NULL;
    111.             }
    112.         }
    113.     }
    114.  
    115.     SetLastError(TL_LastError);
    116.  
    117.     return(ptd);
    118. }
     
  3. Vituskosoy

    Vituskosoy New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2009
    Сообщения:
    18
    osox, спасибо за обширную информацию, но я надеялся на более простой ответ.
    Сервер у меня в консольном режиме работает нормально, а вот в оконной программе, я не знаю куда запихнуть "цикл извлечения запросов на подключение из очереди", чтобы не тормозить работу программы.
    Запустить в виде отдельного потока или существует более правильное решение?
     
  4. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    Vituskosoy
    чем поток не устраивает?
     
  5. Vituskosoy

    Vituskosoy New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2009
    Сообщения:
    18
    RedLord, все понял, все устраивает.
     
  6. Vituskosoy

    Vituskosoy New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2009
    Сообщения:
    18
    Подскажите, как преобразовать тип?
    Процедуре потока по умолчанию передается тип LPVOID, в который я заношу адрес структуры SOCKET. Чтобы использовать эту структуру в потоке приходится проделать следующее:
    Код (Text):
    1. SOCKET mysocket;
    2. CreateThread(NULL, NULL, MyServer, &mysocket, NULL, NULL);
    3. ...
    4.  
    5. DWORD WINAPI MyServer(LPVOID lpv)
    6. {
    7.     SOCKET mysocket;
    8.     mysocket = ((SOCKET *)lpv)[0];
    9. }
    А можно как-то упростить, чтобы в потоке не создавать дополнительный сокет, а использовать тот, на который ссылается аргумент?
     
  7. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Код (Text):
    1. SOKET *pmysoket = (SOKET *)lpv
    2. pmysoket->...
     
  8. Vituskosoy

    Vituskosoy New Member

    Публикаций:
    0
    Регистрация:
    31 дек 2009
    Сообщения:
    18
    google, спасибо, буду знать.
    Если бы не ответили, удалил бы свой пост, что-то меня глюкануло, просто надо было этот сокет прописать в глобальной области и использовать в потоке :)))
     
  9. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    Вопросы
    1. Как создать в си массив переменной длины и с ним работать? есть ли стандартные средства?
    2. Не посоветуете коротенькую книгу по основам си (нужно быстро научиться писать незамысловатые программы).
     
  10. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    1 в Си стандартных средств нет в С++ есть
    2 чтобы писать незамысловатые программы нужны знания к C/C++ не имеющие никакого отношения
     
  11. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    osox
    Переформулирую: нужен справочник по синтаксису си и его основным процедурам/функциям, таким как abs, printf и пр.
     
  12. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    The Standard C Library by P.J. Plauger
     
  13. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Expert C Programming: Deep C Secrets. By Peter van der Linden
     
  14. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    osox
    спасибо!
     
  15. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Керниган, Ричи. "Язык C" Компактное изложение, разжеваны указатели, в частности какую связь они имеют с массивами (динамическими в том числе). Кстати в С99 можно писать int a[n] а не только через calloc.
     
  16. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    J0E
    только выделив через int a[n] память в стеке динамически
    нельзя перераспределить побольше блок в отличии от простого calloc
    а перераспределять таки часто надо

    в этом контексте таки динамические массивы бесполезны но вот в таких местах как
    формальные аргументы функций и создание указателя на массив намного удобней
    стало таки да :)
     
  17. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Если помню С, объявление можно делать всегда после {
    for ( size_t s = 1; ; s <<= 2 ) { int a[n]; }
     
  18. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    можно да но я не о том вот к примеру есть у нас int a[n]; и все если нам надо увеличить на три(к примеру) байта массив у нас ничего не получится это похоже на alloca можно динамически выделить в стеке немного места но нельзя перераспределить буфер в стеке нет realloca а полезность в виде формальных параметров стала очевидной там где раньше писали hardcode или вручную подсчитывали местоположение элемента при передаче матриц теперь можно формальный параметр описать так void recalc_matrix(int n, int m, int matrix[n][m]){} а ранше нам бы пришлось написать так void recalc_matrix(int n, int m, int matrix[n][/*hardcode*/]){} или так void recalc_matrix(int n, int m, int matrix[]){} и вручную подсчитать расположение ну вообщем главная их полезность на мой взгляд это то что теперь стало можно при объявлении массива указать размер переменной но не больше нельзя ни пересрапределить ничего но удобно динамически создавать указатели на кусок памяти разного размера char (*p10)[var_10] указатель на 10 байт а раньше бы пришлось хардкодить char (*p10)[/*hardcode*/];
     
  19. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    Здравствуйте!

    Помогите, пожалуйста, перевести сей код на Си в качестве ассемблерной процедуры-вставки.
    Код (Text):
    1. DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
    2.       ; Switch on wifi
    3.       PUSH EAX  ; for future
    4.       PUSH EDX
    5.       CLI
    6.       MOV  DX, 118Fh
    7.       MOV  AL, 12h
    8.       OUT  DX, AL
    9.       MOV  DX, 118Eh
    10.       MOV  AL, 80h
    11.       OUT  DX, AL
    12.       STI
    13.       POP  EDX
    14.       POP  EAX
    15.  
    16.       MOV  EAX, STATUS_DEVICE_CONFIGURATION_ERROR
    17.       RET
    18. DriverEntry endp
    Не понимаю, почему компилятор gcc ругается на строчку с cli и константами для mov после моего перевода..

    p.s.
    Код (Text):
    1. STATUS_DEVICE_CONFIGURATION_ERROR equ 00C0000182h
    2. PDRIVER_OBJECT equ DWORD
    3. PUNICODE_STRING equ DWORD
     
  20. heed

    heed New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    21
    Переводите используя AT&T-синтаксис , или используете "-masm=intel" в коммандной строке компилятора ?
    // тоже интересно как это делается.