Closed roman-kruglov closed 3 years ago
Вітання, я спробував запустити hunspell через valgrid на Linux і мені нічого не показало. Але «^весь» має працювати лише для слова «весь» (і не працювати для «увесь»). І наскільки я бачу, принаймні на Linux воно похідні форми (напр. «всього») розпізнає. Я можу спробувати зробити виняток для цього випадку, щоб не було неоднозначності. Але варіант «[^в]есь» виправлення вилучить похідні від «весь», ви б не могли перевірити? Якщо так, то може «(^весь)» натомість спрацює, поки я не закину виняток?
Напишу окремо, щоб не плутатися. Щодо valgrind на Linux.
Можливо у вас якась інша версія hunspell? Я спробував на двох версіях - якась близька до 1.6 та останній master коміт. В обох версіях ці умови проходили один і той же шлях, приблизно
bool AffixMgr::parse_affix(const std::string& line,
const char at,
FileMgr* af,
char* dupflags)
.....
// piece 5 - is the conditions descriptions
std::string chunk(start_piece, iter); // here chunk == "^весь"
reverseword(chunk); // here it is something like "....^" - what's important, the ^ at the end now
reverse_condition(chunk);
де всередині reverse_condition одразу йде
void AffixMgr::reverse_condition(std::string& piece) {
if (piece.empty())
return;
int neg = 0;
for (std::string::reverse_iterator k = piece.rbegin(); k != piece.rend(); ++k) {
switch (*k) { // here *k == '^' on the first iteration
...
case '^': {
if (*(k - 1) == ']') // here it accesses a byte outside (after) piece's std::string buffer. Usually it != ']', but some other stuff. It could be though
neg = 1;
else
*(k - 1) = *k; // usually it goes here, overwriting the next byte after original chunk std::string buffer. UB
break;
}
А яке приладдя використовували с valgrind? MemCheck за замовчуванням?
Наскільки я зрозумів по тим небагатьом шматочкам інформації, що я знайшов про формат афікс файлів, якщо «^весь» має працювати лише для слова «весь», то може там повинно бути просто "весь"? Тоді воно мабуть спрацює і коли "весь" буде просто в кінці слова, а не окремим словом. Якщо такі бувають.
Мабуть там ^ і означала - початок строки \ слова. Але мені здається конкретно для цієї директиви (SFX опис правила, мабуть так воно називається) в коді такої можливості не задумано. Хоча бачив для деяких інших директив таку можливість. А ось що буде, якщо (^весь) - не знаю, мабуть спрацює. Спробую.
Варіант «[^в]есь» гадаю справді вилучить похідні від «весь», я чогось подумав що так і задумано.
А хіба.. воно не повинно і для «увесь» працювати? Усього, усьому, усім, уся, усієї, усе - google ai не бачить у цих словах проблем. Ну то може вже я тонкощі не розумію.
Наприклад тут http://manpages.ubuntu.com/manpages/bionic/man5/hunspell.5.html - спробуйте пошукати символ ^ по цій сторінці, для суфіксів (і префіксів) він згадується лише як
(4) condition. Zero stripping or affix are indicated by zero. Zero condition is indicated by dot. Condition is a simplified, regular expression-like pattern, which must be met before the affix can be applied. (Dot signs an arbitrary character. Characters in braces sign an arbitrary character from the character subset. Dash hasn't got special meaning, but circumflex (^) next the first brace sets the complementer character set.)
але функціонал, схожий на той, що ви намагалися використати, є для іншої директиви афікс файлів:
REP what replacement This table specifies modifications to try first. First REP is the header of this table and one or more REP data line are following it. With this table, Hunspell can suggest the right forms for the typical spelling mistakes when the incorrect form differs by more than 1 letter from the right form. The search string supports the regex boundary signs (^ and $).
хоча не впевнений, що підійде.. Просто я так розумію функціонал для афіксів (суфіксів, префіксів) може взагалі задуманий тільки для частин слів?
Спробував варіант з (^весь)
. Ну, словник завантажився, MSVC не скаржиться, ніби в тому місці немає проблеми. Спробував перевірити слово. Не впевнений як правильно було б перевірити саме цю ситуацію, але на обидва слова "сього" і "вього" видає в списку першим "всього". Слова "всього", "всьому", "весь", "всім" - вважає правильними. Це ті, що я спробував. Якщо підкажете як ще перевірити - зроблю.
Напишу окремо, щоб не плутатися. Щодо valgrind на Linux.
Можливо у вас якась інша версія hunspell? Я спробував на двох версіях - якась близька до 1.6 та останній master коміт. В обох версіях ці умови проходили один і той же шлях, приблизно ... А яке приладдя використовували с valgrind? MemCheck за замовчуванням? Так, типовий valgrind з memcheck hunspell 1.7.0 Не псує, але додав тестів і схоже ^весь не працює, відпишу докладніше нижче
хм.. хоча якщо поміркувати, то виходить, що можливо воно не в сусідню пам'ять, а останній "нульовий" символ заміняє. Але це також нічого доброго не зробить. Може тому valgrind не бачить, бо воно формально у той же самий буфер пише, який строка виділила.
Ну якщо там далі десь скопіювати в інший інстанс std::string, то воно орієнтуватиметься на .size(), яке не орієнтується на нульовий символ. А ось якщо на цій "зіпсованій" строці спробують .c_str(), то гадаю біда буде. Ну, може не в чужу пам'ять, але за межу початку ітератора точно. Якщо не помиляюся, все ще Undefined Behavior (UB).
Але варіант «[^в]есь» виправлення вилучить похідні від «весь», ви б не могли перевірити? Якщо так, то може «(^весь)» натомість спрацює, поки я не закину виняток?
Фактично тут ідея в тому, щоб від «весь» генерувало «всьому», але від «увесь» не генерувало «увсього» (правильно «усього»). Тобто треба дві перевірки - «всього» має бути ок, а «увсього» - ні. Й тут у мене другий тест не проходить. Я гляну, чи варто це просто занести у виняток, чи зробити (^весь) - тоді, схоже, все гаразд.
Спробував у себе - з варіантом (^весь)
для всіх тих суфікс правил в словнику - «всього» вважає правильним, «увсього» вважає невірним, пропонує "усього", "всього", "у всього". Ніби працює, як потрібно.
Перепрошую, не відповів на інше питання: словника окремо власне української лексики у мене немає.
І дуже дякую за звіт про проблему!
Був радий допомогти! Вдячний вам за роз'яснення, а то б невірний варіант використав.
Вітаю!
Коли завантажував ваш словник у Hunspell під дебагером MSVC - стабільно псується пам'ять на наступних строках:
місце у коді, якщо знадобиться:
там де
*(k - 1)
- одразу виходить за межі у чужу пам'ять. А потім ще і записує в неї символ ^. А там як пощастить, що там в динамічній пам'яті поряд розташувалося. Але UB 100%.Оновлення до останніх версій і словника і Hunspell не допомогли - в словнику ці строки наявні і в Hunspell код вище не відрізняється.
Я не впевнений на 100%, як повинно бути, але мені зда'ється з того, що я знайшов про формати словників, і того що видно з коду - ^ у цьому випадку може бути використана лише після [ або (.
Ось як я виправив ці строки, ніби відповідає початковому задуму, якщо я його вірно вгадав:
так працює ніби нормально, принаймні пам'ять не псує. Нажаль я знайшов це у вже готових словниках, а де у вас виправити тут у репозиторії - не певен.
П.С. вдячний вам за ваші чудові словники і вашу роботу, дуже важлива справа!
До речі, у вас випадком немає у словниках окремо власне української лексики (незапозичені слова, конкретно не (спільні \ схожі) на російські)? Або можливо знаєте, де можна знайти? Поки що нажаль не зміг знайти нічого подібного. Хочу створити колоду для Anki.