Понятно, что идя за буфер ошибок (или создает переполнение), но что произойдет, если менее 12 байт, используемое в 12 байт буфера? Это возможно или пустая трейлинг всегда наполняют 0С? Ортогональный вопрос, что может помочь: что содержится в буфере, когда он создается, но не используется приложением еще?
Я посмотрел несколько программ питомца в Visual Studio и кажется, что они добавляются с 0С (или нулевые символы), но я не уверен, если это МС осуществления, которые могут варьироваться в зависимости от языка/ компилятора.
Возьмем следующий пример (внутри блока кода, а не глобальные):
char data[12];
memcpy(data, "Selbie", 6);
Или даже такой пример:
char* data = new char[12];
memcpy(data, "Selbie", 6);
В обоих случаях, описанных выше, первые 6 байт данные
В С
,Е
,л
,б
,я
, и E
. Остальные 6 байт данных рассматриваются как "энное" и (может быть что угодно).
Есть ли возможность или пустые трейлинг всегда наполняют 0С?
Не гарантируется на всех. Единственный распределителя, я знаю, что гарантий ноль байт заполнения с памятью. Пример:
char* data = calloc(12,1); // will allocate an array of 12 bytes and zero-init each byte
memcpy(data, "Selbie");
что содержится в буфере, когда он создается, но не используется приложением еще?
Технически, как в самые последние стандарты c++, байты выступил распределитель технически считать, что "энное" по. Вы должны понимать, что это'данных мусора (что-нибудь). Не делайте никаких предположений о содержании.
Отладки с помощью Visual Studio часто будет инициализировать буферы с с 0xcc или 0xcd
ценности, но что не так в релизных сборках. Однако компилятор флаги и методы распределения памяти для Windows и Visual Studio, где вы можете гарантированно нулевой инициализации выделения памяти, но это не портативный.
В C++ есть классы для хранения, включая глобальные, автоматический и статический. Инициализация зависит от того, как переменная объявлена.
char global[12]; // all 0
static char s_global[12]; // all 0
void foo()
{
static char s_local[12]; // all 0
char local[12]; // automatic storage variables are uninitialized, accessing before initialization is undefined behavior
}
Некоторые интересные подробности здесь.
Рассмотреть свой буфер, заполненный нулями:
[00][00][00][00][00][00][00][00][00][00][00][00]
Теперь давайте's пишут 10 байт на него. Значения увеличение от 1:
[01][02][03][04][05][06][07][08][09][10][00][00]
И теперь опять, на этот раз, 4 раз как 0xFF:
[FF][FF][FF][FF][05][06][07][08][09][10][00][00]
что произойдет, если меньше 12 байт, используемое в 12 байт буфера? Это возможно или пустая трейлинг всегда наполняют 0С?
Вы пишите так, как вы хотите, оставшиеся байты остаются неизменными.
ортогональные вопрос, что может помочь: что содержится в буфере, когда Это создается, но не используется приложением еще?
Энное. Ожидаем мусор, оставленный программ (или другие части вашей программы), которые используют эту память раньше.
Я посмотрел несколько программ питомца в Visual Studio и кажется, что они добавляются с 0 (или нуль-символы), но я не уверен, если это МС осуществления, которые могут варьироваться в зависимости от языка/ компилятора.
Это именно то, что вы думаете. Кто-то сделал это за вас в этот раз, но нет никаких гарантий, что это произойдет снова. Это может быть флаг компилятора, который придает чистке кода. Некоторые версии в MSVC используется для заполнения свежей памяти с 0xCD, когда побежал в отладки, но не в релизе. Она также может быть оснащены системой безопасности, которая стирает память, прежде чем давать его в свой процесс (так что вы можете'т шпионить за другими приложениями). Всегда помните, чтобы использовать функцию memset для инициализации буфера, где это важно. В конце концов, мандат использование определенных флаг компилятора в README, если вы зависите от свежего буфера содержат определенное значение.
Но уборка это не нужно. Взять 12 байтовый буфер. Вы заполнить его с 7 байт. Потом вы передаете его куда-то - а вы говорите, что "Вот 7 байт для тебя". Размер буфера не имеет значения при чтении. Вы ожидаете, что другие функции, чтобы прочитать столько, сколько вы'вэ написано, а не как можно больше. В самом деле, в C это, как правило, не позволяет сказать, сколько буфер.
И примечание стороны:
По понятным причинам, идет через буфер ошибок (или создает переполнение)
Это не'т это'проблемы С. Что's, почему это'ы огромную проблему безопасности: ошибки нет, а программа пытается продолжить, поэтому он иногда выполняет вредоносный контент, он не хотел. Поэтому нам пришлось добавить кучу механизмов операционной системы, как экспресс-панель, что позволит увеличить вероятность сбой программы и уменьшите вероятность его продолжения с повреждены памяти. Таким образом, не зависят от тех, задним числом охранников и смотреть ваши буферной границы себя.
Программа знает длину строки, так как она заканчивается С нуль-Терминатор, персонаж нулевого значения.
Именно поэтому для того, чтобы соответствовать строку в буфер, буфер должен быть хотя бы 1 символ больше, чем количество символов в строке, так что он может поместиться в строке плюс нуль-Терминатор тоже.
Любое пространство после этого в буфере остается нетронутым. Если данные есть, то все равно нет. Это то, что мы называем мусором.
Неправильно считать это пространство заполнены нулями только потому, что вы еще'т использовать его, вы не'т знаю, что это конкретное пространство памяти используется для Прежде чем ваша программа дошла до этого места. Неинициализированной памяти должны быть обработаны, как если бы то, что в нем является случайным и ненадежным.
Все предыдущие ответы очень хорошие и очень подробные, но ОП, кажется, быть новыми для программирования C. Таким образом, я думал реальный мир пример может быть полезным.
Представьте, у вас есть держатель стойки напиток, который может вместить шесть бутылок. Это'ы сидели в гараже, так что вместо шести бутылок, он содержит различные сомнительные вещи, которые накапливаются в углах гаражей: пауки, дома мышь, и соавт.
Компьютер, буфер немного, как это только после того, как вам передать его. Вы можете't действительно быть уверен, что's в это, ты просто знаешь, насколько она велика.
Теперь давайте'говорят, что вы положили четыре бутылки в свой держатель. Ваш держатель Не'т изменить размер, но вы теперь знаете, что's в четырех пространств. Два других пространств, с их сомнительного содержания, до сих пор нет.
Компьютер буферы таким же образом. Что's, почему вы часто видите параметр bufferSize переменную, чтобы отслеживать, сколько из буфера в использовании. Лучше бы имя numberOfBytesUsedInMyBuffer но программисты, как правило, быть безумно немногословны.
Письменной части буфера не влияет на неписаные часть буфера; он будет содержать все, что было заранее (что, естественно, полностью зависит от того, как вы получили буфера на первом месте).
В качестве другого ответа отмечает, статические и глобальные переменные будут сброшены в 0
, но локальные переменные не инициализированы (и вместо того, чтобы содержать все, что было на заранее стека). Это согласуется с нулевыми затратами, принцип: инициализация локальных переменных, в некоторых случаях может быть нежелательной и ненужной во время выполнения стоимости, в то время как статические и глобальные переменные выделяется во время загрузки, так как часть сегмента данных.
Инициализация хранилища кучи по выбору диспетчер памяти, но в целом он не будет инициализирован, либо.
Я думаю, что правильный ответ заключается в том, что вы всегда должны отслеживать, сколько чар написаны. Как с низкого уровня функции, такие как читать и писать нужно или дать количество символов читать или прописан. Таким же образом, СТД::строка сохранить следы количество символов в implementatiin
В общем, это's не удивительно для буферов underfull. Это'ы часто хорошая практика, чтобы выделить буферы больше, чем они должны быть. (Пытается всегда вычислить точный размер буфера является частым источником ошибок, и часто пустая трата времени.)
Если буфер больше, чем он должен быть, когда буфер содержит меньше данных, чем выделенный размер, это'ы, конечно, важно, чтобы отслеживать, сколько данных это есть. В целом есть два способа сделать это: (1) с явной рассчитывать, хранить в отдельной переменной, или (2) с помощью "Страж" и значения, такие как \0
символ, который отмечает конец строки в C.
Но потом там's вопрос, если не все буферной В использовать, что делать неиспользуемые элементы содержат?
Один ответ, конечно же, что это не'т материи. Что'ы что "неиспользованные" и означает. Вы заботитесь о ценностях записи, которые используются, которые приходятся на ваш счетчик или дозорного значение. Вы Don'т заботиться о неиспользуемых значений.
В принципе существует четыре ситуации, в которых вы можете предсказать начальные значения неиспользуемые записи в буфер:
Когда вы выделяете массив (включая символьный массив) с статическая продолжительность, неиспользуемые элементы инициализируются 0.
Когда вы выделяете массив и дать ему явного инициализатора, все неиспользуемые элементы инициализируются 0.
Когда ты называешь с памятью
, выделенная память инициализирована все-Дид-0.
Когда вы называете функції strncpy, строка назначения на подкладке на размер
нс
символы\0`.
Во всех остальных случаях неиспользованные части буфера непредсказуемы, и, как правило, содержат все, что они делали в прошлый раз (что бы это ни значило). В частности, вы не можете предсказать содержание неинициализированного массива с автоматическая длительность (то есть той, что'ы местные функции, и это'т заявил, с "статический"), и вы не можете предсказать содержание памяти, полученные с функция malloc
. (Какое-то время, в этих двух случаях памяти, как правило, начинают как все-бит-ноль в первый раз, но вы наверняка не'т хотим, чтобы когда-нибудь зависеть от этого.)
Это зависит от класса памяти спецификатор, реализации и настройки. Некоторые интересные примеры:
0xCCCCCCCC
0xCDCDCDCD
Заявленные объекты статических продолжительность (те, объявленная вне функции, или со "статичными", квалификация), которые не имеют указанного инициализации инициализируются все значения будут представлены в буквальном ноль, т. е. ноль целое число, с плавающей точкой нулевой, или пустой указатель, если это уместно, или структуры или объединения, содержащие такие значения]. Если декларацию любого объекта (в том числе автоматического продолжительность) включает в себя инициализатор, участки, значения которых определяются, что инициализатор будут установлены так, как указано, а оставшаяся часть будет обнулена, как со статическими объектами.
Для автоматических объектов без инициализаторов, ситуация несколько более неоднозначно. Дал что-то вроде:
#include <string.h>
unsigned char static1[5], static2[5];
void test(void)
{
unsigned char temp[5];
strcpy(temp, "Hey");
memcpy(static1, temp, 5);
memcpy(static2, temp, 5);
}
стандартная понятно, что "тест" не бы вызвать неопределенное поведение, даже если он копирует части темп
, которые не были инициализированы. Текст стандарта, по крайней мере, из С11, непонятно, будет ли что-нибудь гарантированно о ценностях static1[4]
и static2[4]
, особенно ли они могут остаться проведении различных значений. Отчет дефекта указано, что стандарт не был предназначен, чтобы запретить компилятору от себя, как если бы код был:
unsigned char static1[5]={1,1,1,1,1}, static2[5]={2,2,2,2,2};
void test(void)
{
unsigned char temp[4];
strcpy(temp, "Hey");
memcpy(static1, temp, 4);
memcpy(static2, temp, 4);
}
которые могли бы оставить static1[4]и
static2[4], имеющие разные значения. Стандарт не содержит никаких указаний относительно качества компиляторы, предназначенные для различных целей должен вести себя в этой функции. Стандарт также предлагает руководство о том, как функция должна быть написана, если намерение если программист требует, чтобы static1[4]
и static2[4]
имеют одинаковую ценность, но не'т волнует, что это значение.