Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>>Хуже. Она использует __declspec(thread). Иначе, сам подумай, что будет, если ее начнут из разных потоков вызывать
GZ>>Для этого достаточно одного потока.
PD>Только при некорректном использовании.
Некорректное использование — это, например, случайный реентер.
void parse_line(line* line);
void parse_text(char* text)
{
int n = 0;
char* line;
for(line=strtok(text,"\n"); line; line=strtok(NULL,"\n"))
{
++n;
printf("line #%d", n);
parse_line(line);
}
}
void parse_line(line* line)
{
int n = 0;
char* word;
for(word=strtok(line," "); word; word=strtok(NULL," "))
++n;
printf(" has %d words\n", n);
}
Всё-таки, что ни говори, а strtok — ублюдочная функция. По двум причинам:
1) у неё есть внутреннее состояние, которое можно сбить
2) типичное приложение — цикл — требует двух различных, но согласованных вызовов:
for(token=strtok(source,pattern); token; token=strtok(NULL,pattern))...
а это — провокация к технологии copy-paste и различным ошибкам (начиная с очепяток).
Можно же было запомнить pattern вместе с курсором строки — раз уж вообще что-то запоминаем.
for(token=strtok(source,pattern); token; token=strtok(NULL,NULL))...
Хотя можно было написать вот такое, без внутренних состояний:
char* strtok2(char** /*inout*/ source, char* pattern)
{
char* token = **source ? *source : NULL;
*source += strcspn(*source, pattern);
*(*source++) = 0;
return token;
}
.....
while( token=strtok2(&source,pattern), token!=NULL )
.....
убивающее сразу трёх зайцев:
— реентерабельно
— приложения без копипаста
— за попытку раскоцать строковый литерал компилятор надаёт по пальцам (разумеется, это обходится... но уже не так просто и бездарно)
Беда сишной библиотеки — в том, что таких глупостей там хватает. Например, функции работы со временем.
И если компилятор не поддерживает TLS (а это, в общем, геморройное дело) — то многопоточное CRT оказывается не совместимо со стандартом (в котором эти глупости есть). Пример: VxWorks.