2015-11-25 4 views
-4

У меня есть этот фрагмент кода в C++:Почему неинициализированный массив символов заполнен случайными символами?

char x[50]; 
cout << x << endl; 

, который выводит случайные символы, как показано здесь: enter image description here

Итак, мой первый вопрос: какова причина этого выхода? Разве это не пробелы или по крайней мере одни и те же символы?

Причина в том, что я пишу программу в CUDA, и я делаю манипуляции с персонажами внутри функции __global__, поэтому использование string дает ошибку «вызывающей функции хоста». Но если я использую массив символов «достаточно большой» (каждый кусок текста, который я использую с разным размером, что означает, что он не всегда будет использовать массив символов), он иногда не заполняется полностью, и я остался с барахлом, как на картинке ниже висит в конце текста:

enter image description here

Так что мой второй вопрос: есть ли способ избежать этого?

+3

в чем причина? - вы не инициализировали его. Есть ли способ избежать этого? - Да, инициализируйте его. – user463035818

+0

Итак, есть ли короткий способ инициализировать его пробелами? – Schizo

+0

https://www.google.de/search?q=init+char+array&ie=utf-8&oe=utf-8&gws_rd=cr&ei=NgRWVsacJorSU4L0vJgL – user463035818

ответ

2

В чем причина этого выхода?

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

[...] иногда не полностью заполнены, и я ушел с мусором [...]

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

Есть ли способ избежать этого?

Да. Инициализируйте его.

+0

@Downvoter Причина для downvote? Я что-то забыл? – Downvoter

0

Нет, нет способа избежать этого. C++ не инициализирует автоматические переменные встроенных типов (например, массивы встроенных типов в вашем случае) автоматически, вам нужно их инициализировать самостоятельно.

1

(предположим x86 на этом посту)

, что является причиной этого выхода?

Вот примерно то, что происходит, в сборке, когда вы делаете char x[50];:

ADD ESP, 0x34 ; 52 bytes 

По существу, стек перемещается вверх 0x34 байт (должно быть кратно 4).Затем это место в стеке становитсяx. Там нет очистки, никаких изменений или толчков или попсов, просто это пространство становится x. Все, что было до этого (оставленные параметры, обратные адреса, переменные от предыдущих вызовов функций), будет в x.

Вот примерно то, что происходит, когда вы делаете new char[50]:

1. Control gets passed to the allocator 
2. The allocator looks for any heap of sufficient size (readas: an already allocated but uncommited heap) 
3. If 2 fails, the allocator makes a new heap 
4. The allocator takes the heap (either the found or allocated one) and commits it 
5. The address of that heap is returned to your code where it is used as a char* 

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

Есть ли способ избежать этого?

В случае динамической памяти, вы можете перегрузить new и delete операторы в C++ и всегда нулевой вновь выделенную память. Вы можете увидеть примеры перегрузки этих операторов here. Что касается памяти в стеке, вам просто нужно постоянно обнулять ее.

ZeroMemory(myArray, sizeof(myarray)); 

В качестве альтернативы, для обоих методов, вы можете остаться в стороне от открытого массива и использовать зЬй :: вектор или другие оболочки, которые берут на себя инициализацию для вас. Тем не менее, вы все равно захотите инициализировать целые числа и другие числовые или указательные типы данных.

0

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

char x[50]; 
cout << new char[50] << endl; 
cout << x << endl; 

Вы пропускаете память с помощью «нового символа [50] без соответствующего удаления.

Кроме того, неинициализированная память не определена, как говорили другие, и в большинстве случаев вы получаете мусор внутри этого блока памяти. Лучше всего это инициализировать его:

char x[50] = {}; 
char* y = new char[50](); 

Тогда просто не забудьте вызвать delete на y позже, чтобы освободить память. Да, ОС сделает это за вас, но это никогда не означает, что можно писать хорошие программы.

+0

Я понимаю всю суету о утечке памяти, но это была просто демонстрация. :) Я бы никогда не писал эту строку с оператором 'new' ... – Schizo

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