Вы выделяете, используя sizeof(array)
, что является неправильной требуемой единицей распределения.
Похоже, вам нужны два разных типа выделения памяти или объекты.
Первый - это массив указателей на символьные строки, поскольку данные файла представляют собой последовательность символьных строк.
Второй вид выделения памяти - для памяти, в которой хранится фактическая строка символов.
Первый вид выделения памяти для массива указателей на символьные строки:
char **pArray = malloc (100 * sizeof(char *)); // allocate the array of character string pointers
Второй вид выделения памяти для символьной строки, которая представляет собой массив символов, будет:
char *pString = malloc ((256 + 1) * sizeof(char)); // allocate a character array for up to 256 characters
256 + 1
необходим для того, чтобы выделить пространство для 256 символов плюс еще один для конца строки.
Таким образом, чтобы выделить все необходимое пространство, вы должны сделать следующее:
int iIndex;
int nMax = 100;
char **pArray = malloc (nMax, sizeof(char *)); // allocate array of rows
for (iIndex = 0; iIndex < nMax; iIndex++) {
pArray[iIndex] = malloc ((256 + 1) * sizeof (char)); // allocate a row
}
// now use the pArray to read in the lines of text from the file.
// for the first line, pArray[0], second pArray[1], etc.
Использование realloc()
Был задан вопрос об использовании функции realloc()
для настройки размера выделенной памяти.
Для второго вида памяти, памяти для фактической строки символов, главное - использовать realloc()
как обычно, чтобы увеличить или уменьшить объем памяти. Однако, если память сокращается, вам необходимо рассмотреть, была ли усечена текстовая строка, и предоставлен ли новый конец конца строки, чтобы обеспечить правильное завершение текстовой строки с помощью индикатора конца строки.
// modify size of a text string memory area for text string in pArray[i]
// memory area. use a temporary and test that realloc() worked before
// changing the pointer value in pArray[] element.
char *p = realloc (pArray[i], (nSize + 1) * sizeof (char));
if (p != NULL) {
pArray[i] = p; // valid realloc() so replace our pointer.
pArray[i][nSize] = 0; // ensure zero terminator for string
}
Если вы гарантируете, что когда область памяти для pArray]
установлена после NULL после выделения массива, вы можете просто использовать функцию realloc()
, как описано выше, без предварительного использования malloc()
, так как если указатель в аргументе на realloc()
равно NULL, тогда realloc()
просто сделает malloc()
для памяти.
Для первого типа памяти вам нужно будет рассмотреть вопрос об освобождении любой памяти, указатели которой могут быть уничтожены при сокращении выделенного массива. Это означает, что вам нужно будет немного больше управлять и хранить данные управления о выделенной области памяти. Если вы можете гарантировать, что вы будете только увеличивать размер массива и никогда не сокращать его, то вам не нужно выполнять какое-либо управление, и вы можете просто использовать тот же подход, который предусмотрен для второго типа памяти выше.
Однако, если память, выделенная для первого типа памяти, должна быть как меньше, так и больше, вам необходимо иметь представление о размере выделенной области памяти. Вероятно, самым простым было бы иметь простой struct
, который бы обеспечивал как указатель на выделенный массив, так и максимальное количество элементов, которые может содержать массив.
typedef struct {
size_t nCount;
char **pArray;
} ArrayObj;
Предупреждение: следующий код не был протестирован или даже скомпилирован. Также обратите внимание, что это работает только в том случае, если выделение памяти будет увеличено.
Тогда вы бы обернули функцию realloc()
в функцию управления. Эта версия функции обрабатывает только если realloc()
всегда для расширения массива. Если сделать его меньше, вам нужно будет обработать этот случай в этой функции.
ArrayObj ArrayObjRealloc (ArrayObj obj, size_t nNewCount)
{
// make the management a bit easier by just adding one to the count
// to determine how much memory to allocate.
char **pNew = realloc (obj.pArray, (nNewCount + 1) * sizeof (char *));
if (pNew != NULL) {
size_t ix;
// realloc() worked and provided a valid pointer to the new area.
// update the management information we are going to return.
// set the new space to NULL to have it in an initial and known state.
// initializing the new space to NULL will allow for knowing which array
// elements have a valid pointer and which don't.
obj.pArray = pNew;
for (ix = nNewCount; ix >= obj.nCount; ix--) {
obj.pArray[ix] = NULL;
}
obj.nCount = nNewCount;
}
return obj;
}
и используйте эту функцию что-то вроде
AnyObj obj = {0, NULL};
// allocate for the first time
obj = ArrayObjRealloc (obj, 100);
// do stuff with the array allocated
strcpy (obj.pArray[i], "some text");
// make the array larger
obj = ArrayObjRealloc (obj, 150);