Использование malloc дает мне больше памяти, чем ожидалось? - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь справиться с malloc, и до сих пор я получаю неожиданные результаты, когда тестирую и играю с ним.

int main(int argc, char** argv)
{
    int size = 10;
    int *A;
    A = (int *)malloc(size * sizeof(int));
    for (int i = 0; i < 10000; i++)
    {
        A[i] = i;
    }
    for (int i = 0; i < 10000; i++)
    {
        printf("%d) %d\n", i, A[i]);
    }
}

Например, в приведенном выше примере кода код выполняется без ошибок. Несмотря на то, что я выделил A только для 10 * int, я ожидал, что цикл будет выполнен только 10 раз, прежде чем произойдет ошибка. Если я увеличу цикл примерно до 30-40 Кбайт, он попадет в ошибку сегментации. Однако, если я увеличу свой размер до величины цикла, она всегда будет работать так, как ожидалось. Так что я знаю, как избежать ошибки .. вроде, я просто надеялся, что кто-то может быть настолько любезен, чтобы объяснить, почему это так.

Edit: Оказалось, я не оценил, что C не обнаруживает вне границ, Java и C ++ слишком много заботили меня. У меня было неопределенное поведение , и теперь я знаю, что моя работа - предотвращать их. Спасибо всем, кто ответил.

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Неопределенное поведение не означает «гарантированная ошибка сегментации»; это может работать в некоторых случаях.

Нет способа узнать, как далеко за пределами массива вы можете пройти до того, как наконец-то произойдет сбой; даже разыменование одного элемента за границей - неопределенное поведение.

Также: если malloc успешно, он выделит как минимум столько места, сколько вы запросили, возможно, больше.

0 голосов
/ 09 января 2019

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

Изобразите это так:

<UNAVAILABLE><other data>1234567890<other data><UNAVAILABLE>

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

0 голосов
/ 09 января 2019

C не требуется для проверки границ доступа к массиву. Это может позволить вам читать / писать после этого без каких-либо предупреждений или ошибок.

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

Если программа может аварийно завершить работу, это еще не значит, что она произойдет.

...