LINUX.ORG.RU

выскажите мнение о фазах луны в С/С++

 


0

1

привет.

спор возник, на тему того, почему программа, в которой использование висячего указателя раньше не валило программу, а сейчас валит.

мне-то все понятно, но коллега не верит что это может произойти просто из-за фазы луны, не говоря уже про смену железа/компилятора/версию ОСи, етц...

и да, программа имеет отчасти асинхронную природу. и да, недавно программа переехала на более мощный сервер.

спасибо.

★★★

Последнее исправление: cetjs2 (всего исправлений: 2)

И раньше, и сейчас, программа использовалась с одними и теми же либами, одним и тем же способом, все действия в точности повторялись, и остальные процессы в системе вели себя точно так же, поэтому абсолютно ничто не могло повлиять на решения операционной системы и аллокатора относительно расположения выделяемой памяти?

ilammy ★★★
()

Я вот тоже сейчас смотрю на один интерпретатор. На некоторых системах падает. На некоторых нет. На одной программе падает, но стоит добавить в неё лишнюю строку — уже нет. Пока иксы не стояли — падала. Поставил DE, чтобы посмотреть в графическом отладчике — уже всё хорошо. UB оно такое.

ilammy ★★★
()

Пинками выгони его на улицу и пусть гуляет там до тех пор, пока не найдёт 10 копеек. А потом спроси у него откуда они там взялись. Он их туда положил? Нет. Но они там были. Хотя их там наличие нелепо.

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

Хотя их там наличие нелепо.

энтропия, епс =)

niXman ★★★
() автор топика

Царь еще не приползал? Не объяснял почему никсман - нулёвое ничтожество, а плюсы - говно?

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

Это не Undefined Behavior. UB значит, что реализация может быть какой угодно. Но если не менять версию компилятора и библиотек, то они поведут себя одинаково.

Здесь дело может быть в том, что память выделяется системой сразу большим куском. И то, что ты в программе сделал free(), фактически не вернуло системе память, то есть процесс всё ещё может туда обращаться. Это при одной фазе луны. При другой фазе луны память выделилась по-другому и обращение по висячему указателю было поймано железом.

kvap
()
Последнее исправление: kvap (всего исправлений: 1)
Ответ на: комментарий от anonymous

ну, ты же царь. раздвоение личности, однако.

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

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

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

т.е. по твоему, использование висячего указателя это нормально при условии что не будет производиться смена компилятора/библиотек? =)

niXman ★★★
() автор топика

Думать чему будет равен указатель после malloc всё равно, что думать чему будет равен результат rand, в программе активно его использующей. Нет, это даже сложнее, потому что реализация алгоритма выделения может меняться в разных версиях ядра (в том числе минорных) и libc, а реализация rand не изменна.

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

UB это не использование висячего указателя, а использование неоднозначного кода. Например, ++i + ++i - это UB. И таки при одной версии компилятора (и одинаковых опциях оптимизации) это будет работать вполне стабильно. А висячий указатель может упасть от изменения поведения не только компилятора, но и любого другого компонента системы. Или даже просто от изменения количества и последовательности действия пользователей приложения.

Может быть приложение перенесли на новый сервер, оно смогло обрабатывать больше запросов в секунду, память стала выделяться активнее... и висячий указатель дал о себе знать. Причина проявления этой ошибки может быть абсолютно любой.

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

++i + ++i - это UB

Сфигали? Где здесь неоднозначность? Не все ли равно, как слагаемые местами переставишь?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от niXman

Это ошибка времени выполнения, которая просто не всегда возникает, когда ты обращаешься к висячему указателю (железо не может следить за принадлежностью каждого байта). И она не имеет отношения к языку Си.

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

Это не Undefined Behavior. UB значит, что реализация может быть какой угодно. Но если не менять версию компилятора и библиотек, то они поведут себя одинаково.

Это называетсся Implementation Defined Behaviour, обращение к ранее освобождённому куску памяти именно Undefined Behavior

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

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

т.е. это не «UNdefined behavior», это «defined behavior»?

зы

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

всем спасибо, вопрос закрыт.

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

Да. Компилятору совершенно очевидно какой код следует сделать для обращения к висячему указателю (и он в общем-то не знает, что указатель висячий). Поведение будет зависеть не сколько от компилятора, сколько от алгоритма аллокации памяти.

UB это когда стандарт не даёт однозначного ответа на вопрос как распарсить какую-то конструкцию. Но в случае висячего указателя код с точки зрения компилятора абсолютно корректный и однозначный.

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

Стандарт не гарантирует, что это всё будет присвоено i в тот же момент. Новое значение может быть присвоено уже после вычисления всего выражения.

KivApple ★★★★★
()

но коллега не верит что это может произойти просто из-за фазы луны, не говоря уже про смену железа/компилятора/версию ОСи, етц...

Твой коллега - анскильнутый кодер, которого надо дрессировать методом кнута и электрошока.

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

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

поведение программы с висячими указателями, гарантировано?

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

UB это когда стандарт не даёт однозначного ответа на вопрос как распарсить какую-то конструкцию.

Чушь же. Неоднозначность разбора это синтаксическая или грамматическая ошибка, к UB никакого отношения не имеет. UB это неопределённое действие или результат от синтаксически корректного и валидного кода. Обращение к dangling pointer это UB.

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

Если интересно, что конкретно происходит в двух случаях, то надо смотреть на оба аллокатора (libc). Их интерфейс к системе неизменен — brk+mmap, тут разницы не должно быть. Возможно второй аллокатор тупо по-другому выделяет/освобождает блоки из-за другого лимита по памяти или других параметров. Возможно он устроен слегка по-другому. Возможно libc раньше делала одну подготовительную работу, а теперь другую, и по-разному использовала malloc, что привело к другому паттерну выделения в том месте. Гадать можно долго, проще поставить брейк в месте освобождения и зайти отладчиком внутрь free, подключив сорцы libc.

Undefined и defined behavior оба являются behavior, оба как-то детерминированно себя ведут (а не от погоды на марсе, как любят долдонить местные недоучки) и отличаются только тем, что одно чеько определено/описано (defined), а другое нет. Ваш кэп.

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

Может и быть гарантировано, если под этим ты понимаешь одинаковое поведение на определенном наборе параметров платформы. Внезапно, undefined и гарантировано ортогональны.

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

Представь, я написал функцию int do_something(int a, int b), и заявил, что если a = 0, то b должно быть > 0, иначе behavior is undefined. А сам в своей либе втихаря вызываю do_something(0, -2) для внутренних целей. Себе-то я гарантирую, что при этом произойдет, а тебе не рассказал, хотя планирую оставить такой интерфейс навсегда, чтобы не иметь проблем с abi в будущем.

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

поведение программы с висячими указателями, гарантировано?

Нет. Даже если висячий указатель имеет одно и то же значение при всех запусках программы, на падучесть можно влиять извне, например, размером стека. Канонический пример:

#include <stddef.h> /* size_t */
#include <stdio.h>

int main(int argc, char * argv[])
{
    const char * p = (const char *)&argc; /* dangling pointer */
    size_t off     = 16 * 1024; /* some pages */
    printf ("stack trash at %p+%zu: %02X\n", p, off, *(p+off));

    return 0;
}

Читаем чуть ниже текущего положения стека. Падает или нет? Может зависеть от, например, текущего окружения:

$ ./a
Ошибка сегментирования
$ export ENV="`seq 1 10000`"
$ ./a
stack trash at 0x7fff2e240cfc+16384: 30
$ ./a
stack trash at 0x7fffd4dfe60c+16384: 31
$ ./a
stack trash at 0x7fff7bd88e2c+16384: 36

valgrind ошибок не детектит.

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

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

я написал функцию int do_something(int a, int b), и заявил, что если a = 0, то b должно быть > 0, иначе behavior is undefined. А сам в своей либе втихаря вызываю do_something(0, -2) для внутренних целей.

это называется implmentation defined, как выше уже говорили.

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

если память была освобождена, а программа выполняется в многозадачной среде - все, приехали, любой сторонний процесс прося память у ОСи, может получить именно ту область памяти.

в общем, печально на ЛОРе, совсем печально.

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

> valgrind ошибок не детектит.
так он бестолковый же. юзай AddressSanitizer, он такой код сразу прибьет.

Вопрос был не о том, чем детектить, не?

И не прибьёт:

$ gcc-4.9.1 -fsanitize=address a.c -o a # можно clang :]
$ ./a
ASAN:SIGSEGV
=================================================================
==11671==ERROR: AddressSanitizer: SEGV on unknown address 0x7fffd6a16edc (pc 0x000000400875 sp 0x7fffd6a12ed0 bp 0x7fffd6a12ef0 T0)
    #0 0x400874 in main (/tmp/a+0x400874)
    #1 0x7fa68d351a64 in __libc_start_main (/lib64/libc.so.6+0x21a64)
    #2 0x400748 (/tmp/a+0x400748)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 main
==11671==ABORTING

$ ENV="`seq 1 10000`" ./a
stack trash at 0x7fff29f992fc+16384: 33
$ ENV="`seq 1 10000`" ./a
stack trash at 0x7fffeb6ea7dc+16384: 39
sf ★★★
()
Ответ на: комментарий от sf

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

да, это я напутал.

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

я написал, что если ..., иначе behavior is undefined

это называется implmentation defined

Разупорись, уходи, читай, чем два термина отличаются. Когда поймешь, что это интент, а не классификация, тогда приходи.

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

если память была освобождена, а программа выполняется в многозадачной среде - все, приехали, любой сторонний процесс прося память у ОСи, может получить именно ту область памяти.

Я немного не уследил.

Что должно «плавать» в поведении процесса, в котором освободили память?

На что влияет наличие или отсутствие других процессов в данном конкретном случае?

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

Плавает тут только тс, уперся в свои неверные представления, уже скатился на аргументацию уровня «ты идиот». Щас погуглит, придет.

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

так он бестолковый же. юзай AddressSanitizer, он такой код сразу прибьет.

Он не может сделать тут большего чем делает valgrind, т.к. формально память выше текущего кадра стека может быть валидной и все обращения к ней тоже легитимны. Только из кода нельзя понять ошибочное это обращение или легитимное.

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