Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
DavidTs
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
1

Почему malloc работает не так, как ожидается?

08.03.2016, 14:04. Просмотров 1198. Ответов 13
Метки нет (Все метки)

C
1
2
3
4
5
6
7
8
9
int main()
{
 
    int* p =malloc(sizeof(int));
    p[100]=5;
    printf("%s\n",strerror(errno));
    printf("%d",*(p+100));
    return 0;
}
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.03.2016, 14:04
Ответы с готовыми решениями:

Почему цикл работает не так, как ожидается?
Двумя способами реализовал цикл, который увеличивает годовую зарплату на 10% при нажатии 'y' до тех...

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

Почему при вводе элементов массива, программа прекращает работу или работает не так, как ожидается?
При вводе элементов массива, программа прекращает работу или не правильно работает. Например если...

#define работает не так, как ожидается
Здравствуйте. Подскажите, пожалуйста, почему в таком случае некорректно использовать #define: ...

13
Mirmik
techpriest
631 / 210 / 57
Регистрация: 27.02.2014
Сообщений: 1,170
08.03.2016, 14:10 2
А не так, это как?
0
zss
Модератор
Эксперт С++
9266 / 8002 / 4911
Регистрация: 18.12.2011
Сообщений: 21,339
Завершенные тесты: 1
08.03.2016, 14:13 3
C++
1
2
3
4
    int* p =malloc(sizeof(int)*101);
....
free(p);
return 0;
0
DavidTs
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
08.03.2016, 14:19  [ТС] 4
Mirmik, I gave memory just for one integer and initialized the 100th element, but it works correctly.

Добавлено через 3 минуты
zss, это понятно, я так сделал специально, чтобы получить ошибку, но почему errno возвращает success?
0
Nick Alte
Эксперт С++
1658 / 1030 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
08.03.2016, 14:20 5
DavidTs, это undefined behavior. Никто специальную проверку не делает, выходит ли программист за пределы массива или нет, ошибку такую не ловит. Было бы затратно на каждое обращение к массиву и прочие элементарные действия лепить проверки и диагностики. Предполагается, что программист сам принимает меры и пишет программу корректно.
1
Mirmik
techpriest
631 / 210 / 57
Регистрация: 27.02.2014
Сообщений: 1,170
08.03.2016, 14:45 6
DavidTs На самом деле, malloc особенно ничего не делает. Он следит только затем, чтобы в следующий раз не выдать указатель на ту же ячейку памяти. Это уведомительная операция.

Вы сказали:
- Эй Маллок, куда мне положить мой объект размера int.
- Клади сюда, - сказал Маллок и отвернулся...

А вы пошли в другую сторону и положили свой инт еще куда-то... Вот собственно и всё, никто вам этого не запрещает.
0
Хрисипп
19 / 29 / 13
Регистрация: 09.02.2016
Сообщений: 219
08.03.2016, 17:01 7
вообще тут интересные вещи происходят. Когда ты обратился к элементу несуществующего массива, создался этот массив, но он забрал все доступное ему место(не знаю от чего зависит,но в C++ выделилось раза в два больше места). НО это происходит только с указателями и только,если этот самый указатель пустой и под него выделено место

...даже и не знаю где про это можно почитать
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
6331 / 3081 / 834
Регистрация: 18.10.2014
Сообщений: 5,803
08.03.2016, 20:00 8
Уже сто раз об этом писали в соседней ветке
Память освобождается, но значение остается
Память освобождается, но значение остается

Защита памяти от некорректного доступа выполняется на уровне ОС. Библиотека времени выполнения (БВВ) не передает каждый из ваших 'malloc'-ов в ОС, а просто сначала запрашивает у ОС один большой блок памяти, внутри которого уже БВВ сама занимается раздачей памяти под ваши маленькие объекты. Поэтому пока вы своим некорректным доступом попадаете внутрь этого большого блока, нарушения защиты памяти происходить не будет (с точки зрения ОС все в порядке) и будет даже казаться, что "все работает".

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

Разумеется, говорить, что исходный пример "работает" - наивная ерунда. Поведение программы в любом случае не определено. Вы лезете в память, которая вам не принадлежит и с рук вам это сходит только в вашем искуственном микроскопическом примере. В реальной программе дело закончится существенно более печально: либо вы разрушите "чужие" данные, либо в будущем новый запрос памяти будет размещен в этом месте и разрушит ваши данные.

Добавлено через 3 минуты
Цитата Сообщение от Хрисипп Посмотреть сообщение
вообще тут интересные вещи происходят. Когда ты обратился к элементу несуществующего массива, создался этот массив, но он забрал все доступное ему место
Ничего подобного здесь, разумеется, не происходит и никакого массива, который "забрал все доступное ему место" не создается. Все здесь просто, банально и уже давно разжевано вдоль и поперек. Непонятно, почему такие темы до сих пор вызывают у кого-то такое недоумение.
0
DavidTs
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
08.03.2016, 20:07  [ТС] 9
nick]Mirmik[/nick], TheCalligrapher, Спасибо. А здесь по той же причине после второго вызова calloc () sbrk не перемещается?
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
 
 
int main()
{
    printf("first_brk __ %p\n",sbrk(0));
    int* ptr = calloc(5,sizeof(int));
    printf("ptr = %p\n", ptr);
 
    printf("after_first_alloc_brk __ %p\n",sbrk(0));
 
    char* char_ptr = calloc(3,sizeof(char));
    printf("char_ptr = %p\n",char_ptr);
    printf("after_second_alloc_brk __ %p\n",sbrk(0));
    return 0;
}
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
6331 / 3081 / 834
Регистрация: 18.10.2014
Сообщений: 5,803
08.03.2016, 20:41 10
Лучший ответ Сообщение было отмечено DavidTs как решение

Решение

Цитата Сообщение от DavidTs Посмотреть сообщение
А здесь по той же причине после второго вызова calloc () sbrk не перемещается?
Совершенно верно. Как вы видите, что при первом вызове 'calloc' 'sbrk' перемещается на существенно большее расстояние чем нужно было. Например здесь он перемещается на ~135Kb, хотя попросили вы всего ~20 байт. Это и есть память, заранее отхваченная у системы "на будущее". И пока она вся не распределится внутренними механизмами БВВ, перемещения 'sbrk' наблюдаться не будет (по крайней мере для мелких запросов).
0
DavidTs
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
08.03.2016, 21:25  [ТС] 11
TheCalligrapher, спасибо за объяснение.
0
Хрисипп
19 / 29 / 13
Регистрация: 09.02.2016
Сообщений: 219
09.03.2016, 12:57 12
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Ничего подобного здесь
почему же он позволяет обратиться к массиву? с переменной же такое не прокатит
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
6331 / 3081 / 834
Регистрация: 18.10.2014
Сообщений: 5,803
10.03.2016, 01:46 13
Цитата Сообщение от Хрисипп Посмотреть сообщение
почему же он позволяет обратиться к массиву? с переменной же такое не прокатит
Не понимаю, о чем речь. Приведите примеры "позволяет" и "не прокатит".
0
Хрисипп
19 / 29 / 13
Регистрация: 09.02.2016
Сообщений: 219
12.03.2016, 14:35 14
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Приведите примеры
как-то много вопросов возникает, чтобы нормально ответить. лучше уж пойти мне, ламеру, поучиться
0
12.03.2016, 14:35
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.03.2016, 14:35

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

ConstraintSet работает не так как ожидается в Handler
Делаю визуализацию сортировки. Сначала хочу реализовать swap. Два элемента подсвечиваются красным,...

Условие в цикле do while работает не так, как ожидается
Проблема в условие цикла. Вот Код.// ConsoleApplication4.cpp: определяет точку входа для...

Нюансы работы с массивами: почему программа ведёт себя не так, как ожидается?
// ConsoleApplication20.cpp: определяет точку входа для консольного приложения. // #include...

Нюансы работы с оператором ветвления if else: почему программа ведёт себя не так, как ожидается?
Имеется код: int a; char q; for (;;) { cout &lt;&lt; &quot;Введите число: &quot;; cin &gt;&gt; a;


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.