LINUX.ORG.RU

Куча проверок, а всё равно assert

 , ,


0

5

Тут хитрый контекст: я почти не контролирую сборку кода. Программа пишется для Android на Qt.
Более того: ошибка не воспроизводится на моём оборудовании.
Плей Маркет сообщает мне вот что:

backtrace:
 
  #00  pc 000000000001d75e  /system/lib/libc.so (abort+58)
 
  #01  pc 000000000001d9c7  /system/lib/libc.so (__assert2+22)
 
  #02  pc 0000000000016149  /data/app/org.asciigames.fillfield--qxeEjn8vGLqekL2bnvZTg==/lib/arm/libFillField.so (Game::makeMove(int, int)+256)
 
  #03  pc 0000000000017d9f  /data/app/org.asciigames.fillfield--qxeEjn8vGLqekL2bnvZTg==/lib/arm/libFillField.so (ViewGame::tapProcessing(int, int, int)+346)
 
  #04  pc 0000000000126ad7  /data/app/org.asciigames.fillfield--qxeEjn8vGLqekL2bnvZTg==/lib/arm/libQt5Widgets.so (QWidget::event(QEvent*)+322)


А вот кусочки важного кода:
1) tapProcessing(int, int, int)
if (x_field < 0 || x_field > 7)	return;
if (y_field < 0 || y_field > 7)	return;

_game->makeMove(x_field, y_field);


2) makeMove(int, int)
assert(x >= 0 && x <= 7 && y >= 0 && y <= 7);


Да, assert стоит первой же строкой и я ума не могу приложить при каких обстоятельствах он даже теоретически может сработать.

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

«Методом тыка» я ничего проверить не могу. У меня проблема не воспроизводится, с пользователями я пообщаться тоже не могу. Так что решать нужно лишь созерцая код.

Deleted

Насыпь скобочек, оберни все сравнения, а также внутри ассерта, всё в скобочки ((x_field < 0) || (x_field > 7)) ((x >= 0) && (x <= 7) && (y >= 0) && (y <= 7))

Есть возможность добавить больше отладки? Насыпь логирования

anonymous
()
Ответ на: комментарий от anonymous

Ну тут с приоритетами явно всё беспроблемно. Как тут можно ошибиться?
А с отладкой всё плохо:у меня не воспроизводится, а пользователи мне никаких логов да ещё и с Андроида отсылать не будут.
Я вообще беспокоюсь по поводу самого ассерта. Не условия в ассерте, а о нём самом. Это же Андроид да ещё и clang (нынче под Андроид GCC не катит). Может он сам сломан?

Deleted
()

Там ниже в backtrace должны быть аргументы в регистрах, посмотри что прилетает в этот метод, возможно сможешь понять, почему вызывается assert.

Возможно есть другой вызов функции, где нет проверки выше.

EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 2)
Ответ на: комментарий от EXL

Там ниже в backtrace должны быть аргументы в регистрах,

Нет, больше ничего нет. Я полностью скопировал все данные, которые мне предоставил Гугл.

Возможно есть другой вызов функции, где нет проверки выше.

Нет, иначе makeMove из tapProcessing не вызывается. Это было бы слишком просто :)

Deleted
()
Ответ на: комментарий от Deleted

Еслиб в шланге под пендроид сломался бы assert - хлынула бы такая волна говнеца, что твой постец очень быстро бы ей смылся :)

pon4ik ★★★★★
()

assert - валит прогу в корку. Плюс есть всякие поделки которые на terminate автоматически стектрейс собирают и даже отсылают на почту.

pon4ik ★★★★★
()
Ответ на: комментарий от Deleted

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

pon4ik ★★★★★
()

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

Признание того, что исходный код не соответствует бинарю. Смысл тогда строить теории? Достаешь код соотвествующего билда и разбираешься.

anonymous
()
Ответ на: комментарий от anonymous

Где несоотвествие? У пользователей сейчас код с включёнными ассертами. У меня код с включёнными ассертами. О чём ты?

Deleted
()
Ответ на: комментарий от Deleted

Проблема не во «включенных ассертах». Проблема в том, что ты не можешь воспроизвести эксперимент (исходники, сборочное окружение, опакечивание), и пытаешься вспомнить, что, где, когда и как получилось. У тебя нет однозначного соотвествия бинаря и исходников.

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

anonymous
()

Можно попробовать так:

assert(x >= 0);
assert(x <= 7);
assert(y >= 0);
assert(y <= 7);

или даже так:

#undef x
#undef y
assert(x >= 0);
assert(x <= 7);
assert(y >= 0);
assert(y <= 7);
xaizek ★★★★★
()

В общем х.з. что делать.
Пока заменю assert на обычный if. Через пару дней может быть что-то прояснится.

Deleted
()

Сделай сборку вообще без оптимизаций

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от sanwashere

Там всё синхронно. Ну, касательно логики. Что там делает Qt с интерфейсом я могу лишь догадываться, но это не должно влиять.

Deleted
()
Ответ на: комментарий от sanwashere

Да, нажатия. Не должно такого быть, Qt по идее (по моей идее) должен прикрывать мне тыл, но стоит проверить...

Deleted
()

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

Undefined behavior. Оптимизатор мог доказать, что в вызывающей функции условия никогда не выполнится, и выбросить проверки. А в вызываемой функции честно вставить проверки и вызов assert. Ищи проблему в вызывающей функции.

i-rinat ★★★★★
()

В гуглоплее лежит дебажная сборка? Или вы в релизе принудительно включаете assert?

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

В релизе ассерты оказались активированы.

Deleted
()
Ответ на: комментарий от EXL

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

Deleted
()

Чудес я в програмировании както не встречал (а неправельно работающий асерт это самое что ни наесть чудо), всегда находилось какоето логическое объяснение.

Скорее всего у вас в коде ошибка которую трудно увидить/воспроизвести. Что может быть:

*) Банально гдето напутана логика и makeMove дергается в обход базовых проверок

*) x_field / y_field модифицируются до передачи в makeMove (либо уже внутри makeMove до assert идет модификация переменных)

*) Может быть неявная модификаци переменных при передаче по ссылке/адресу в другой метод.

*) Может быть банальное переполнение стека/выход за граници локального буффера и неявная запись по адрессам x/y.

*) Если репорт всего один - то может быть просто у пользователя проблемное железо.

*) Если репортов много и они разные (стек трейсы разные) то возможно у вас в софте идет разрушение памяти (heap corruption) и начинается полная каша (особенно если софт многопоточный).

zaz ★★★★
()
Ответ на: комментарий от EXL

баг компилятора <…> релевантные проверки

Компилятор — не человек, он не может определить релевантность сам по себе. Нужна формальная спецификация.

i-rinat ★★★★★
()
Ответ на: комментарий от EXL

Это тогда скорее баг компилятора, раз он выкидывает настолько релевантные проверки границ.

Чаще всего «баги компилятора» находят начинающие программисты. Но при более внимательном рассмотрении кода и вытирании монитора после его рассмотрения выясняется, что виноват был не компилятор :)

andreyu ★★★★★
()
Ответ на: комментарий от EXL

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

Ты либо очень невезучий, либо выбрал не ту профессию.

anonymous
()

Есть смысл посмотреть результирующий код после препроцессора.

Еще вариант, что ты где-то выстрелил себе в ногу и что-то упустил из-за чего неявно модифицируются данные через указатели, в том числе при работе с классами. Вплоть до выхода за отведенные (подразумеваемые) границы.

praseodim ★★★★★
()
Последнее исправление: praseodim (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Листинг бы ассемблерный, чтобы посмотреть во что оно там превратилось.

@Stahl, ты скинь куда-нибудь либу libFillField.so с этим багом, её можно декомпильнуть в IDA или Ghidra. Если компилятор выкинул проверки, то там это будет видно.

EXL ★★★★★
()
Ответ на: комментарий от EXL

её можно декомпильнуть в IDA или Ghidra

Да никто этим заниматься не будет. Я просто избавился от ассертов (Это Андроид. Я там как-то напоролся на отсутствие в их стандартной либе чего банального уровня atoi) и наблюдаю. Через пару дней станет ясно.
Более того, если проблема таки пропадёт, то тут уже можно будет потехи ради сделать микропример и его уже анализировать, а не довольно большой оригинальный код.

Deleted
()
Ответ на: комментарий от Deleted

Да никто этим заниматься не будет.

Нет, ну если тебе действительно интересно, почему такое происходит, то это первое что ты должен был сделать.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Овчинка выделки не стоит. Читать современный ассемблер после дизассемблирования Си++ это... нужно быть очень целеустремлённым чтобы таким заниматься. Я просто хочу чтобы юзеры не крашились на ровном месте.

Deleted
()
Ответ на: комментарий от EXL

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

Так ведь в топике речь о другой проблеме.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.