2017-02-13 35 views
-1

В соответствии с тем, что я понял о malloc(), это позволяет нам динамически назначать память во время выполнения. Ниже приведен код, который я ищу вКак malloc может принимать большее количество байтов данных, чем назначено

#include<conio.h> 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
void main() { 
    char *description; 
    clrscr(); 
    description = malloc(2*sizeof(char)); 
    strcpy(description,"Hello there!"); 
    printf("%s",description); 
    free(description); 
    printf("%s",description); 
    getch(); 
} 

Мой вопрос я задаю систему назначить 2 байта памяти в функции malloc(). Поэтому, когда я пытаюсь заполнить строку "Hello there!" и напечатать то же самое, я должен получить только первые 2 символа строки в качестве вывода, но я получаю всю строку, которую я дал в strcpy() функции на выходе.

А также после того, как я использую функцию free(), если я попытаюсь напечатать description снова. Я не должен получать какой-либо результат, если я не ошибаюсь, но я все еще получаю одну и ту же строку снова. Можете узнать, как это работает. Я использую компилятор turbo C++.

+7

Вы стреляете в ногу. Это традиционное и дизайнерское решение, которое C-язык позволяет вам стрелять в ногу. – user3528438

+3

Ну, системный язык, такой как C, должен позволять вам стрелять в ногу. Решение состоит в том, чтобы не делать этого. – DeiDei

+4

Чтобы сделать приведенные выше комментарии немного более откровенными, C требует, чтобы вы знали, что, черт возьми, это ваши – StoryTeller

ответ

2

Malloc выделяет 2 байта. Это означает, что из начальной точки (возвращаемой malloc) дайте мне 2 байта. strcpy копирует все байты в строке «привет там!». начиная с адреса в описании. Это не заботится о распределении, оно просто копирует байты. % S в printf сообщает printf искать строку с нулевым завершением.

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

Как указал @Michael Foukarakis, запись байтов в нераспределенной памяти может привести к неопределенному поведению. Если что-то другое должно было писать на нераспределенной памяти между утверждениями, вещи сломаются.

+0

Спасибо, Патрик! Могу ли я узнать, как я могу распечатать данные даже после использования функции free() для освобождения выделения из описания. –

+0

free() используется, чтобы сообщить диспетчеру памяти, что байты могут быть использованы для других целей снова. Он не удаляет данные, которые уже присутствуют. –

+0

Спасибо. что объясняет мои запросы :) –

1

если вы поместили больше данных, тогда размер merery be beiour будет непредсказуемым.

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

1
description = malloc(2*sizeof(char)); 

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

strcpy(description,"Hello there!"); 

Вы пишете в конце прошлой памяти, выделяемой malloc (доказательство: «Привет», имеет длину более 2), поэтому ваша программа вызывает неопределенное поведение.

printf("%s",description); 
free(description); 
printf("%s",description); 

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

Кроме того, попытка напечатать строку (предположительно), на которую указывает description после free(description);, также вызывает неопределенное поведение.

+0

Спасибо, что так хорошо объяснил Майкл. Я действительно стрелял в ногу. –

4

Функция malloc() выделяет как минимум объем запрашиваемой памяти, хотя может быть и больше. Однако объем памяти, который предоставляет malloc(), на самом деле не является центральной проблемой.

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

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

Итак, это аннотированная версия вашей программы.

#include<conio.h> 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
void main() { 
    char *description; // create a variable that will contain the address of a character 
    clrscr(); 
    // allocate an array of characters. the number of characters is 2 so this 
    // will allocate a minimum size memory area that will hold 2 characters. 
    // malloc() may round up the size or it may not but all you can count on 
    // is 2 characters in size. 
    description = malloc(2*sizeof(char)); 
    // copy a constant string to the memory location pointed to by the variable 
    // description. the strcpy() function does not check on the limits of the 
    // memory. after the malloc() is done there is no size information available 
    // to strcpy() or any other of the C runtime library functions in the C Standard Library 
    // this is copying 11 characters plus the end of string for a total of 12 characters 
    // so to be correct the memory area pointed to by description should be at least 
    // 12 characters however we know from the malloc() above it is guaranteed to 
    // be only 2 characters so we are going past the memory area with this strcpy(). 
    strcpy(description,"Hello there!"); 
    // however we get lucky and it works anyway. 
    printf("%s",description); 
    // tell the memory allocation library that you are done with the memory and it 
    // can be used for something else now. the pointer will probably still be good 
    // for a while because the memory allocation, which gets its memory from the 
    // operating system, does not normally give any freed memory back to the OS. 
    // instead it normally just keeps it until the application terminates. 
    // as long as this freed memory is not used for something else, more than 
    // likely whatever you put there will remain there as is. however the moment 
    // the memory is given to something else, the values will change. 
    free(description); 
    printf("%s",description); 
    getch(); 
} 

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

#include<conio.h> 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
void main() { 
    char array1[12] = { 0 }; 
    char array2[2] = { 0 }; 
    char array3[12] = { 0 }; 
    char *description; 
    printf("Before\n array1 %s\n", array1); 
    printf(" array2 %s\n", array2); 
    printf(" array3 %s\n", array3); 

    description = &array2[0]; 
    strcpy(description, "Hello there!"); 
    printf("description %s\n", description); 

    printf("\nAfter\n array1 %s\n", array1); 
    printf(" array2 %s\n", array2); 
    printf(" array3 %s\n", array3); 
} 

с помощью Visual Studio 2013 и работает в режиме отладки, я получаю предупреждение о памяти переписывается, как завершает приложение. Когда я делаю сборку и запускаю ее, ошибок нет, и я получаю следующий вывод. Как вы можете видеть, функция strcpy() просто скопировала символы, переписывающие смежную память. Похоже, что компилятор Visual Studio 2013 выравнивает память на двойной границе слова, так что в соседней области памяти видны только последние несколько символов строки. Visual Studio заполнила переменную array2[] так, чтобы следующая переменная была разделена на двойную границу слова.

Before 
    array1 
    array2 
    array3 
description Hello there! 

After 
    array1 
    array2 Hello there! 
    array3 ere! 

Если мы изменяем выше программы к следующему:

#include<conio.h> 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
void main() { 
    char array1[12] = { 0 }; 
    char array2[2] = { 0 }; 
    char array3[12] = { 0 }; 
    char *description; 
    int *values; 
    printf("Before\n array1 %s\n", array1); 
    printf(" array2 %s\n", array2); 
    printf(" array3 %s\n", array3); 

    description = &array2[0]; 
    strcpy(description, "Hello there!"); 
    printf("description %s\n", description); 

    printf("\nAfter\n array1 %s\n", array1); 
    printf(" array2 %s\n", array2); 
    printf(" array3 %s\n", array3); 

    description = malloc(8 * sizeof(char)); 
    strcpy(description, "this"); 
    printf("\n\nMalloc\n first description %p %s\n", description, description); 
    free(description); 

    values = malloc(1 * sizeof(int)); 
    *values = 0; 
    printf(" pointer %p and value %d\n", values, *values); 
    printf(" second description %p %s\n", description, description); 

} 

Тогда мы получаем следующий вывод. В этом случае нам повезло и нам дали ту же область памяти на malloc()int, поэтому, когда мы изменили int, мы также изменили область, на которую указывает description, потому что после ее освобождения malloc() повторно использовал область для следующего выделения.

Before 
    array1 
    array2 
    array3 
description Hello there! 

After 
    array1 
    array2 Hello there! 
    array3 ere! 


Malloc 
    first description 00944B28 this 
    pointer 00944B28 and value 0 
    second description 00944B28 

Ресурс собственности Принцип

Этот пример демонстрирует два правила при использовании malloc() и free().

Выделите malloc() сумму, в которой вы нуждаетесь, и не превышайте объем запрашиваемой памяти. Если вам нужно больше, посмотрите на функцию realloc().

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^