Jump to Navigation

Я прийшов, тебе нема

Вот есть такой вызов, strnlen:

     size_t
     strnlen(const char *s, size_t maxlen);

DESCRIPTION
     The strnlen() function attempts to compute the length of s, but never scans beyond the
     first maxlen bytes of s.
И он есть, например, в Mac OS X 10.7 и новее.

Берем код с этим вызовом, собираем с -mmacosx-version-min=10.5 (должен получиться совместимый c 10.5 код, да?) на 10.8, несем на 10.6, запускаем.

Все падает.

И ладно бы падало с внятным сообщением, вот не могу залинковать такое. Нет, SIGSEGV, нулевой указатель (на функцию?).

После этого начинаешь любить Win32 особенно остро.

Comments

давай полный пример - попробую понять то

а так :
LIBRARY
Standard C Library (libc, -lc)

вы не любите кошек - вы просто не умеете их готовить
(с) народ

У меня Qt, поэтому вот прямо оттуда пример:
qtest.pro:

SOURCES+=qtest.cpp
macx:QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.5
CONFIG+=debug_and_release

qtest.cpp:

#include
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget p;
if(!strnlen(argv[0],3)<2) a.exit();
p.show();
return a.exec();
}

Собираем на 10.8, macdeployqt, несем на 10.6:

Process: qtest [1528]
Path: /Users/lexa/qtest/qtest.app/Contents/MacOS/qtest
Identifier: com.yourcompany.qtest
Version: ??? (???)
Code Type: X86-64 (Native)
Parent Process: launchd [108]

Date/Time: 2014-02-20 18:02:11.027 +0300
OS Version: Mac OS X 10.6.8 (10K549)
Report Version: 6

Interval Since Last Report: 47004 sec
Crashes Since Last Report: 11
Per-App Crashes Since Last Report: 1
Anonymous UUID: D54F2D5C-E974-4538-849C-AED41224EBF2

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
Crashed Thread: 0 Dispatch queue: com.apple.main-thread

Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 ??? 000000000000000000 0 + 0
1 com.yourcompany.qtest 0x0000000100001d44 start + 52
....

Меняем strnlen на strlen - и все отлично работает.

Вот чего man strnlen говорит в линуксе

#include

size_t strnlen(const char *s, size_t maxlen);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

strnlen():
Since glibc 2.10:
_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
_GNU_SOURCE

Может проблема при компиляции?

Вдогонку у Кути вроде есть qstrnlen?

Ну у меня этот код в dll/библиотеке, которая без Qt.

Просто чтобы репорт нормальный получить в макоси - нужна 'Application', а я ее без Qt не умею делать.

Какая проблема, если бинарник, собранный на 10.8 - прекрасно на это 10.8 работает?

Ну и в вызов чего strnlen препроцессором при других define выльется? (Одна из версий).

Так как man strnlen на 10.6 пустой - выльется в невозможность линковки.

Проверю чуть позже
но вот думаю что strnlen не проверяет входные параметры на NULL

У меня там НЕТУ null. Строка, на стеке.

Т.е. я заменил strnlen на mystrnlen - как рукой сняло. И это уже не первый случай с strnlen и маком 10.6, грабли уже хоженые.

Во, вот такой вот код:

#include

int main(int ac, char *av[])
{
if(strnlen(av[0],5)<3) return 1;
return 0;
}

Компилируем на 10.8. Запускаем. Работает. Несем бинарник на 10.6, запускаем, illegal instruction.
Надеюсь, нет сомнений, что в av[0] не NULL?

нету у меня уже 10.6
но давай проверим тебя :)
вот этим

#include
#include

int main(int ac, char *av[])
{
printf("is NULL:%p\n", av[0]);
if(strnlen(av[0],5)<3) return 1;
return 0;
}

если не NULL -> бага в strnlen

Я вот этим проверил:

#include

int main(int ac, char *av[])
{
char bytes[]="bytes";
if(strnlen(bytes,5)<3) return 1;
return 0;
}

Та же самая херня, Illegal instruction (несем бинарник с 10.8 на 10.5).
При этом, на 10.6 оно не соберется, потому что strnlen нету.

И, повторяю, это не бага в библиотеке, это в динамической линковке.

В 10.6 в libc(.so/.dylib) нету strnlen

>И, повторяю, это не бага в библиотеке, это в динамической линковке.

видать я это и пропустил :)

да хеза,
последнее - это как бы лихая проблема поддержки старого окружения...врядли даже проверяется...
обычно только совместимость вперед :)

Так в посте ж написано

> И ладно бы падало с внятным сообщением, вот не могу залинковать такое.

Разве strnlen есть в win32?

Она там вроде бы в msvcrt???.dll которую приходится носить с собой (а разные индусы ещё и норовять впилить в system32)?

Ну да, она в рантайме. И рантайм этот приходится таскать с собой. что плохо. Но зато он всегда один и тот же. Что хорошо.

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

Windows

Remarks:
strnlen , wcsnlen, and _mbsnlen do not validate their parameters. If str is NULL, an access violation occurs.

http://msdn.microsoft.com/en-us/library/z50ty2zh.aspx

вот что кстати тут мне подсоветывали:
>the only way to be sure is to compile with the 10.6 sdk, but you will have to copy it manually in the right place from an old xcode version

Не, ну какой 10.6sdk, если я хочу один бинарник, работающий везде, включая ретину.

Хожу, блин, как по минному полю (аналогичная проблема есть в районе STL, блин) с этим макосем.

хех ... вожусь тут с android ... тоже хочу перемен :)

известные проблемы это не проблемы - это фичи :)

Не "должен получиться", а "specify the minimum version supported by your application".
Насколько я понимаю логику создателей всей системы - предполагается, что указав поддерживаемые версии, ты гарантируешь, что про подобные функции знаешь, и огородишь их использование проверками.
https://developer.apple.com/library/mac/documentation/macosx/conceptual/...

Но в целом согласен, неочевидненько. Особенно если оная минимальная версия была указана с какой-нибудь банальной целью вроде избавиться от warning'ов при использовании системного OpenSSL'я.

Прикол с libc, в частности, в том, что там версия макоси "начиная с которой оно есть" - не указана. Вот, например: https://developer.apple.com/library/mac/documentation/Darwin/Reference/M...

Второй прикол - это плюсовая библиотека (std::string и прочая). Мало того, что версии не указаны, там не хватает временами всяких странных потрохов (где-то в глубине реализации) о коих и не подозреваешь. То есть вот базовый класс есть, а сработает он или нет - никогда неизвестно заранее, смотря какие методы позовутся.

Тут, понятно, хорошего решения нет, но вот диагностику бы улучшить хотя бы, не по sigsegv падать хотя бы (в некоторых случаях так и происходит, но я не уловил системы)

На самом деле, если покопаться - то вся информация о времени появления есть заголовочных файлах. Если вопрос стоит практически - то можно попробовать поиграться с max version, и получить всё в виде warning'ов/ошибок при сборке.

Ну практически - можно weak linking запретить и смотреть что йобнется. Хотя вот сдается мне, что от этого испортится не только мой код, но и чужой (Qt)

Любили бы Win, сделали бы RPP для неё )

Где я и где RPP....

значит опять напутал )

Add new comment