2015-10-15 7 views
1

У меня есть символ **, который предназначен для хранения и неизвестно количество строк с неизвестной длинойОбъем памяти для выделения массива строк?

Я первоначально было выделено 10 байт с помощью

char **array = malloc(10); 

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

array[num] = malloc(strlen(source)+1) 

Я заметил, что моя программа падает при добавлении 6-го элемента в массив

Вопрос: как работает память с этими массивами? Когда я выделил 20 байт, ничего не произошло, но когда я выделил 30, он внезапно мог содержать 10 элементов. Это были все строки размером 2-3 символа. Я изо всех сил думать о состоянии перераспределить память с, например

if condition{ 
    memoryofarray += x amount 
    realloc(array, memoryofarray) 
} 

Что именно использует память в полукокса **? У меня создалось впечатление, что каждый байт соответствует количеству строк, которые они могут удерживать, т. Е. Malloc (10) позволит массиву удерживать 10 строк. Мне нужно знать это, чтобы установить условия +, чтобы знать, сколько нужно увеличить память, выделенную массивом.

Кроме того, как ни странно, когда я malloced

array[num] = malloc(0) 

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

+0

'char **' is ** not ** and array! – Olaf

+0

У вас есть ошибка где-то. Найдите это, а затем посмотрите, остались ли какие-либо вопросы/заблуждения. – juanchopanza

+0

'a char **' не является, каким-либо образом, массивом – Magisch

ответ

2
  1. Это будет выделить память для 10 указателей на символ (char*) в массиве

    char **array = malloc(10*sizeof(array[0])); 
    

    В системе 64bit размер char* составляет 8 байт = 64 бит. Размер char обычно составляет 1 байт = 8 бит.

  2. Преимущество использования sizeof(array[0]) вместо sizeof(char*) заключается в том, что в будущем легче изменить тип array.

  3. char** является указателем к указателю на char. Он может указывать на начало блока памяти в куче с указателями на char. Аналогично char* является указателем на char, и он может указывать на начало блока памяти char в куче.

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

    array[num] = malloc(0); 
    

    Вы можете случайно не получить дефект сегментации (удачи).

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

    if (condition) { 
        memoryofarray += amount; 
        array = realloc(array, memoryofarray); 
    } 
    
2

Если вы хотите провести 10 строки, то вам нужно выделить память для 10char *-х и затем выделить память для этих char указателей .Вы выделить память 10 байт (не достаточно для10char * «с) .Allocate, как это -

char **array = malloc(10*sizeof(char *)); // allocate memory for 10 char *'s 

А потом делать то, что вы делаете -

array[num] = malloc(strlen(source)+1) // allocate desired memory to each pointer 

примечание - позаботиться о том, num инициализируется и не получить доступ из связанного индекса.

+0

Это дает место для 10 ** указателей ** для «строки», а не для «струны». – alk

+0

@alk OP выделяет их сам правильно, как упоминалось в вопросе (не проблема, хотя). Это та часть, в которой он имеет проблемы. – ameyCU

+0

Размер char *? было бы просто 10 * sizeof (array)? –

3

Эта линия:

char **array = malloc(10); 

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

Поэтому вы должны убедиться, что вы выделяете массив достаточного размера, используя размер соответствующего типа:

char **array = malloc(10 * sizeof(char*)); 

Теперь, когда у вас есть массив из 10 указателей вам нужно выделить память для каждая из 10 строк, например

array[0] = malloc(25 * sizeof(char)); 

Здесь sizeof(char) не нужен, но я добавил его, чтобы сделать его более очевидным, как таНос работает.

0

Сначала выделить массив указателей:

char* (*array)[n] = malloc(sizeof(*array)); 

Тогда для каждого элемента массива, выделить строки переменной длины по отдельности:

for(size_t i=0; i<n; i++) 
{ 
    (*array)[i] = malloc(some_string_length); 
} 
+1

Предложите 'some_string_length' ->' some_string_length + 1'. – chux

1

Вместо выделения памяти с использованием неисправности склонных стиль

pointer = malloc(n); // or 
pointer = malloc(n * sizeof(type_of_pointer)); 

Использование

pointer = malloc(sizeof *pointer * n); 

Тогда

// Bad: certainly fails to allocate memory for 10 `char *` pointers 
// char **array = malloc(10); 

// Good 
char **array = malloc(sizeof *array * 10); 

как же память с этими массивами работать?

Если выделено недостаточно памяти, оно не работает. Итак, шаг 1: выделить достаточную память.

От array[num] = malloc(0). Выделение 0 может возвращать NULL или указатель на отсутствие записываемой памяти или указатель на некоторая записываемая память.Запись в эту память указателя - неопределенное поведение (UB) в любом из трех случаев. Код может упасть, может «работать», это просто UB. Код не должен пытаться записать этот указатель.

Чтобы быть ясным: «работал без проблем» не означает, что код правильный. C кодируется без сети. Если код делает что-то неправильно (UB), язык не обязан ловить эту ошибку. Поэтому следуйте правилам безопасного программирования.

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