Язык C - Malloc неограниченное пространство? - PullRequest
0 голосов
/ 10 октября 2011

У меня проблемы с изучением malloc и указателя языка C:

Что я выучил до сих пор:

  • Указатель - это указатель адреса памяти.

  • malloc() выделяет ячейки памяти и возвращает адрес памяти.

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

#include<stdio.h>

main()
{
char *x;
x = malloc(sizeof(char) * 5);

strcpy(*x, "123456");
printf("%s",*x); //Prints 123456

}

Я ожидаю ошибку, так как размер, который я указал для malloc, равен 5, где я помещаю 6 символов (123456) в область памяти, на которую указывает мой указатель.Что здесь происходит?Пожалуйста, помогите мне.

Обновление

Где выучить malloc и указатель?Я запутался в звёздочке, например, когда использовать звёздочку и т. Д. Я не успокоюсь, пока не научусь этому!Спасибо!

Ответы [ 5 ]

5 голосов
/ 10 октября 2011

Вы вызываете неопределенное поведение, потому что вы пишете (или пытаетесь писать) за пределами выделенной памяти.

Другие придирки:

  • Поскольку вы используете strcpy()вы копируете 7 байтов, а не 6, как вы заявляете в вопросе.
  • Ваш вызов strcpy() некорректен - вы передаете char вместо указателя на char в качестве первого аргумента.
  • Если ваш компилятор не жалуется, вы не используете достаточно вариантов предупреждений.Если вы используете GCC, вам нужно по крайней мере -Wall в командной строке компилятора.
  • Вы должны включить оба <stdlib.h> для malloc() и <string.h> для strcpy().
  • Вы также должны явно указать int main() (или, лучше, int main(void)).
  • Лично я достаточно стар, чтобы предпочесть увидеть явное return(0); в конце main(), даже если C99 следует C ++ 98 и позволяет вам его опустить.

Возможно, вам не повезло, и вы на некоторое время избегаете вызывать неопределенное поведение, но такой инструмент, как valgrind должен указать на ошибку ваших путей.На практике многие реализации malloc() выделяют кратное 8 байт (а некоторые кратное 16 байтам), и, учитывая, что вы деликатно не перешагиваете 8-байтовое распределение, вы можете сойти с рук.Но хорошая отладка malloc() или valgrind покажет, что вы делаете это неправильно.

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

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

3 голосов
/ 10 октября 2011

Если вы вызываете malloc, вы получаете и адрес области памяти в куче. Если он возвращается, например, 1000 вашей памяти будет выглядеть так:

Adr  Value
----------
1000 1
1001 2
1002 3
1003 4
1004 5
1005 6
1006 0

после вызова strcpy (). Вы написали 7 символов (на 2 больше, чем выделено).

x == 1000 (адрес указателя)

* x == 1 (разыменовывается значение, на которое указывает x)

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

2 голосов
/ 10 октября 2011

Мои три цента:

  1. Используйте x, так как (* x) - это значение, которое хранится в x (что неизвестно в вашем случае) - вы пишете в неизвестное место в памяти. Должно быть:

    strcpy(x, "123456");

  2. Во-вторых, "123456" - это не 6 байтов, а 7. Вы забыли о конце нулевого терминатора.

  3. Ваша программа с текущим кодом может работать, но не гарантируется.

Что бы я сделал:

#include<stdio.h>

main()
{
    char str[] = "123456";
    char *x;
    x = malloc(sizeof(str));

    strcpy(x, str);
    printf("%s",x); //Prints 123456

    free(x);
}
1 голос
/ 10 октября 2011

Во-первых, есть одна проблема с вашим кодом:

x - указатель на область памяти, где вы выделили место для 5 символов. * х это значение первого символа. Вы должны использовать strcpy (x, "123456");

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

0 голосов
/ 10 октября 2011
#include<stdio.h>

main()
{
char *x;
x = malloc(sizeof(char) * 5);

strcpy(x, "123456");
printf("%s",x); //Prints 123456

}

Используйте это ... это будет работать

Смотрите разницу в вашей & моей программе

Теперь здесь вы выделяете 5 байтов и пишете 6 байтов, поэтому 6-й байтбудет сохранен в следующем последовательном адресе.Этот дополнительный байт может быть выделен кому-то еще с помощью управления памятью, поэтому в любое время этот дополнительный байт может быть изменен другой программой , потому что 6-й байт не ваш, потому что вы не сделали это malloc'd .. поэтому это называется неопределенное поведение .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...