выделение памяти в C

У меня есть вопрос относительно порядка выделения памяти. В следующем коде я выделяю в цикле 4 строки. Но когда я печатаю адреса, они, кажется, не выделяются один за другим... Я делаю что-то не так или являюсь этим своего рода защитный механизм, реализованный ОС для предотвращения возможного переполнения буфера? (Я использую Windows Vista).

Спасибо.

 char **stringArr;
 int size=4, i;

 stringArr=(char**)malloc(size*sizeof(char*));
 for (i=0; i<size; i++)
    stringArr[i]=(char*)malloc(10*sizeof(char));

 strcpy(stringArr[0], "abcdefgh");
 strcpy(stringArr[1], "good-luck");
 strcpy(stringArr[2], "mully");
 strcpy(stringArr[3], "stam");

 for (i=0; i<size; i++) {
  printf("%s\n", stringArr[i]);
  printf("%d  %u\n\n", &(stringArr[i]), stringArr[i]);
 }

Вывод:

abcdefgh 9650064 9650128

удача 9650068 9638624

mully 9650072 9638680

штампуйте 9650076 9638736

6
задан thedp 24 January 2010 в 22:26
поделиться

7 ответов

Обычно, когда вы запрашиваете память через malloc(), библиотека времени исполнения С округляет размер вашего запроса до некоторого минимального размера выделения. Это гарантирует, что:

  • библиотека времени исполнения имеет место для своей бухгалтерской информации
  • более эффективно для библиотеки времени исполнения управлять выделенными блоками, которые все кратные некоторому размеру (например, 16 байт)

Тем не менее, это детали реализации, и на самом деле вы не можете полагаться на какое-либо конкретное поведение malloc().

7
ответ дан 8 December 2019 в 04:29
поделиться

Вы не должны зависеть от какого-либо конкретного упорядочения или расстояния, возвращаемого malloc. Это ведет себя в загадочном и непредсказуемым способам.

4
ответ дан 8 December 2019 в 04:29
поделиться

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

Но даже если блоки происходят один друг на друга, они, скорее всего, не образуют смежный блок. Чтобы уменьшить фрагментацию, менеджер кучи только распределяет блоки определенного размера, например мощность двух (64, 128, 256, 512 и т. Д.). Таким образом, если вы зарезервируете 10 байтов для строки, возможно, после этого могут быть 22 или 54 байта.

Настройка памяти - это еще одна причина, по которой не очень хорошая идея использовать динамическое распределение памяти, если не обязательно. Это намного проще и безопаснее просто использовать статический массив.

2
ответ дан 8 December 2019 в 04:29
поделиться

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

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

3
ответ дан 8 December 2019 в 04:29
поделиться

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

4
ответ дан 8 December 2019 в 04:29
поделиться

Я могу подумать двумя способами:

Во-первых, может быть, вы могли бы сделать кормления для ваших моделей ASIGMENTS , pdffiles , а YouTube Ссылка и используйте библиотеку FeedParser , чтобы встроить его в свои новостные представления, это простой способ, поскольку вы можете определить в шаблонах, код для каждого вида новой активности.

Второе, о чем я могу подумать, это сделать класс активность :

class Activity(models.Model):
    date = models.DateTimeField(auto_now_add = True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

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

-121--2387531-

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

Итак?

Я делаю что-то не так или это каким-то образом Оборонный механизм, реализованный ОС для предотвращения переполнения возможных буферов?

, вероятно, «ни один».

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

4
ответ дан 8 December 2019 в 04:29
поделиться

Проверьте директиву переопределения . Вероятно, вам потребуется изменить make-файл один раз, но он должен делать то, что вы хотите.

Пример makefile:

override CFLAGS += -Wall

app: main.c
    gcc $(CFLAGS) -o app main.c 

Пример командных строк:

$ make
gcc -Wall -o app main.c 
$ make CFLAGS=-g
gcc -g -Wall -o app main.c 
-121--996787-

Я не знаю, назначены ли потокам ThreadPool значимые имя , но вы всегда должны иметь возможность использовать ManagedThreadId CurrentThread для отладки/ведения журнала

-121--3119944-

Поскольку вам интересно знать адреса, возвращенные malloc () , вы должны убедиться, что печатаете их правильно. «Правильно» означает, что для печати адресов следует использовать правильный спецификатор формата для printf () . Почему вы используете «% u» для одного и «% d» для другого?

Вы должны использовать «% p» для печати указателей. Это также один из редких случаев, когда вам нужен кастинг в C: поскольку printf () является вариадной функцией, компилятор не может сказать, что указатели, которые вы передаете в качестве аргумента к нему, должны быть типа void * или нет.

Также не следует отдавать возвращаемое значение malloc () .

Исправив вышесказанное, программа:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char **stringArr;
    int size=4, i;

    stringArr = malloc(size * sizeof *stringArr);

    for (i=0; i < size; i++)
        stringArr[i] = malloc(10 * sizeof *stringArr[i]);

    strcpy(stringArr[0], "abcdefgh");
    strcpy(stringArr[1], "good-luck");
    strcpy(stringArr[2], "mully");
    strcpy(stringArr[3], "stam");

    for (i=0; i<size; i++) {
        printf("%s\n", stringArr[i]);
        printf("%p %p\n", (void *)(&stringArr[i]), (void *)(stringArr[i]));
    }
    return 0;
}

и я получаю следующие выходные данные при запуске:

abcdefgh
0x100100080 0x1001000a0
good-luck
0x100100088 0x1001000b0
mully
0x100100090 0x1001000c0
stam
0x100100098 0x1001000d0

На компьютере char * * указатели имеют длину 8 байт, поэтому & stringArr [i + 1] имеет значение 8 байт больше и stringArr [i] . Это гарантируется стандартом: Если вы malloc () некоторое пространство, это пространство является смежным. Вы выделили место для 4 указателей, и адреса этих четырех указателей находятся рядом друг с другом. Вы можете видеть это более ясно, делая:

printf("%d\n", (int)(&stringArr[1] - &stringArr[0]));

Это должно напечатать 1.

О последующих malloc () s, поскольку каждый stringArr [i] получается из отдельного malloc () , реализация может свободно назначать им любые подходящие адреса. На моей реализации, с этим конкретным прогоном, адреса все 0x10 байт друг от друга.

Для вашей реализации кажется, что указатели char * * имеют длину 4 байта.

Похоже, что malloc () выполняет своего рода рандомизацию (что разрешено).

1
ответ дан 8 December 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: