malloc () выделяют непрерывный блок памяти?

В своем сообщении об ошибке вы можете видеть, что ошибка возникает при проверке размеров target . Выходные данные вашей модели без выровненного слоя имеют форму (None, 7, 7), которая правильно отображается в сводке модели. Проблема здесь в том, что ваши метки имеют форму (None, 7), поэтому Keras выбрасывает ValueError (вероятно, при обратном распространении), поскольку ваши метки имеют на одно измерение меньше, чем выходные данные вашей сети. Керас ожидал, что метка (None, 7, 7) будет соответствовать размерам вашего слоя активации, но вместо этого получил (None, 7).

Вот почему использование model.add(Flatten()) перед добавлением плотного слоя работает нормально, так как целевые размеры и выходные размеры оба (None, 7).

35
задан Luuklag 7 October 2018 в 15:27
поделиться

13 ответов

Ответить на Ваши пронумерованные точки.

  1. Да.
  2. Все байты. Malloc/free не знает или заботится о типе объекта, просто размер.
  3. Это - строго говоря неопределенное поведение, но общий прием, поддерживаемый многими реализациями. Посмотрите ниже для других альтернатив.

последний стандарт C, ISO/IEC 9899:1999 (неофициально C99), позволяет участники массива с переменными границами .

пример этого был бы:

int main(void)
{       
    struct { size_t x; char a[]; } *p;
    p = malloc(sizeof *p + 100);
    if (p)
    {
        /* You can now access up to p->a[99] safely */
    }
}

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

, Кроме того, gcc позволяет массивы нулевой длины как расширение. Массивы нулевой длины недопустимы в стандарте C, но gcc представил эту функцию, прежде чем C99 дал нам участников массива с переменными границами.

В ответе на комментарий, я объясню, почему отрывок ниже является технически неопределенным поведением. Числа раздела, которые я заключаю в кавычки, относятся к C99 (ISO/IEC 9899:1999)

struct {
    char arr[1];
} *x;
x = malloc(sizeof *x + 1024);
x->arr[23] = 42;

Во-первых, 6.5.2.1#2 показывает [я], идентично (* ((a) + (i))), таким образом, x-> прибытие [23] эквивалентно (* ((x-> прибытие) + (23))). Теперь, 6.5.6#8 (на добавлении указателя и целого числа) говорит:

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

поэтому, потому что x-> прибытие [23] не в массиве, поведение не определено. Вы могли бы все еще думать, что это хорошо, потому что malloc () подразумевает, что массив был теперь расширен, но это строго не имеет место. Информативное Приложение J.2 (который перечисляет примеры неопределенного поведения) предоставляет дальнейшее разъяснение с примером:

нижний индекс массива вне диапазона, даже если объект по-видимому доступен с данным нижним индексом (как в lvalue выражении a[ 1] [ 7], учитывая интервал объявления [4] [5]) (6.5.6).

49
ответ дан Chris Young 27 November 2019 в 06:37
поделиться

Ответ на вопрос 1 и 2 является Да

Об уродстве (т.е. вопрос 3), что программист пытается сделать с той выделенной памятью?

1
ответ дан hhafez 27 November 2019 в 06:37
поделиться

В ответ на Ваш третий вопрос.

free всегда освобождает всю память, выделенную в единственном выстреле.

int* i = (int*) malloc(1024*2);

free(i+1024); // gives error because the pointer 'i' is offset

free(i); // releases all the 2KB memory
2
ответ дан kiritsuku 27 November 2019 в 06:37
поделиться
2
ответ дан Community 27 November 2019 в 06:37
поделиться

Хотел бы добавить, что не это распространенный, но я мог бы, также назвал это общепринятой практикой, потому что Windows API полон такого использования.

Проверка очень общая РАСТРОВАЯ структура заголовка, например.

http://msdn.microsoft.com/en-us/library/aa921550.aspx

последняя четверка RBG является массивом 1 размера, который зависит от точно этой техники.

2
ответ дан CDR 27 November 2019 в 06:37
поделиться

Я видел и часто использовал этот шаблон.

Его преимущество состоит в том, чтобы упростить управление памятью и таким образом избежать риска утечек памяти. Все это взятия должно освободить malloc'ed блок. Со вторичным буфером Вам будут нужны два свободных. Однако нужно определить и использовать функцию деструктора для инкапсуляции этой операции, таким образом, можно всегда изменять ее поведение, как переключение на вторичный буфер или добавлять дополнительные операции, которые будут выполнены при удалении структуры.

Доступ к элементам массива также немного более эффективен, но это все меньше и меньше значительно с современными компьютерами.

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

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

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

3
ответ дан chmike 27 November 2019 в 06:37
поделиться

Да. malloc возвращает только единственный указатель - как он мог возможно сказать запрашивающей стороне, что он выделил несколько несмежных блоков для удовлетворения запроса?

3
ответ дан Andrew Medico 27 November 2019 в 06:37
поделиться

Что касается № 3, без большего количества кода трудно ответить. Я не вижу ничто плохого с ним, если его случай много. Я имею в виду, Вы не хотите выделять блоки 2 МБ памяти все время. Вы также не хотите делать это напрасно, например, если Вы только когда-либо используете 2k.

то, что Вам не нравится он по некоторым причинам, не достаточно возразить против него или выровнять по ширине полностью перезапись его. Я посмотрел бы на использование тесно, попытаться понять то, что думал исходный программист, тесно ищите переполнение буфера (как workmad3 указанный) в коде, который использует эту память.

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

3
ответ дан i_am_jorf 27 November 2019 в 06:37
поделиться

Я не думаю, что существующие ответы вполне добираются до сущности этой проблемы. Вы говорите, что олдскульный программист делает что-то вроде этого;

typedef struct ts_request
{ 
  ts_request_buffer_header_def header; 
  char                         package[1]; 
} ts_request_def;

ts_request_buffer_def* request_buffer = 
malloc(sizeof(ts_request_def) + (2 * 1024 * 1024));

я думаю, что маловероятно, что он делает точно, что, потому что, если это - то, что он хотел сделать, он мог сделать это с упрощенным эквивалентным кодом, которому не нужны никакие приемы;

typedef struct ts_request
{ 
  ts_request_buffer_header_def header; 
  char                         package[2*1024*1024 + 1]; 
} ts_request_def;

ts_request_buffer_def* request_buffer = 
malloc(sizeof(ts_request_def));

я буду держать пари, что то, что он действительно делает, является чем-то вроде этого;

typedef struct ts_request
{ 
  ts_request_buffer_header_def header; 
  char                         package[1]; // effectively package[x]
} ts_request_def;

ts_request_buffer_def* request_buffer = 
malloc( sizeof(ts_request_def) + x );

то, Чего он хочет достигнуть, является выделением запроса с размером пакета переменных x. Это, конечно, недопустимо для объявления размера массива с переменной, таким образом, он обходит это с приемом. Выглядит, как будто он знает то, что он делает мне, прием находится хорошо к респектабельному и практическому концу масштаба обмана C.

5
ответ дан Bill Forster 27 November 2019 в 06:37
поделиться

Это - стандарт C прием и не более опасно что любой другой буфер.

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

7
ответ дан qrdl 27 November 2019 в 06:37
поделиться

1) Да это делает, или malloc перестанет работать, если не будет достаточно большого непрерывного доступного блока. (Отказ с malloc возвратит Нулевого указателя)

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

3) Это - определенный взлом языка, и немного сомнительный о, это - использование. Это все еще подвергается переполнению буфера также, просто может взять взломщиков немного дольше для нахождения полезной нагрузки, которая вызовет его. Стоимость 'защиты' является также довольно огромной (Вам действительно нужно> буфер 2 МБ за запрос?). Это также очень ужасно, хотя Ваш босс не может ценить тот аргумент:)

7
ответ дан workmad3 27 November 2019 в 06:37
поделиться

3 - Это - довольно общий прием C для выделения динамического массива в конце структуры. Альтернатива должна была бы поместить указатель в структуру и затем выделить массив отдельно и не упущение освободить его также. То, что размер прикреплен к 2 МБ, кажется немного необычным все же.

10
ответ дан TrayMan 27 November 2019 в 06:37
поделиться

Использование (вопрос 3) действительно до интерфейса к этой вашей структуре. В контексте это выделение могло бы иметь смысл, и без дополнительной информации невозможно сказать, безопасно ли это или нет.
, Но если Вы имеете в виду проблемы с выделением памяти, больше, чем структура, это ни в коем случае не плохой дизайн C (я даже не сказал бы, что случается так ЧТО старая школа...;))
Просто заключительное примечание здесь - точка с наличием символа [1] - то, что завершающийся ПУСТОЙ УКАЗАТЕЛЬ всегда будет в заявленной структуре, означая, что может быть 2 * 1024 * 1 024 символа в буфере, и Вы не должны объяснять ПУСТОЙ УКАЗАТЕЛЬ "+1". Мог бы быть похожим на маленький подвиг, но я просто хотел указать.

3
ответ дан E Dominique 27 November 2019 в 06:37
поделиться
Другие вопросы по тегам:

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