2015-01-31 3 views
0

Я работаю над базовой оболочкой (как в консольной программе, ожидающей команды и выполняющей их в системах UNIX) на C, и должен иметь возможность манипулировать 2d массивами char хранить переменные среды.Манипуляция массивами строк в C

Я написал небольшую функцию для создания этого 2d массива и инициализировал каждую строку до NULL, прежде чем заполнить ее в другом месте моего кода. За исключением того, что он сбой, как только программа запускается, по какой-то причине.

У меня есть аналогичные проблемы (а именно случайные segfaults, возможно, из-за того, что я читаю/записываю в неадекватном месте) с двумя другими функциями, соответственно, чтобы освободить эти 2d массивы, когда это необходимо, и получить длину одного из этих 2d-массивов ,

Если я не использую эти две функции и malloc 2d-массив в остальной части моего кода, не инициализируя ничего, кроме последней записи, в NULL, но вместо этого скопируйте строки env непосредственно после malloc, у меня есть что-то, что работает. Но лучше было бы предотвратить утечку памяти и использовать эту функцию ft_tabnew, чтобы я мог повторно использовать ее в будущих проектах.

char  **ft_tabnew(size_t size) 
{ 
    char **mem; 
    size_t i; 

    if (!(mem = (char **)malloc(size + 1))) 
     return (NULL); 
    i = 0; 
    while (i < size + 1) 
    { 
     mem[i] = NULL; 
     i++; 
    } 
    return (mem); 
} 

void ft_tabdel(char ***as) 
{ 
    int i; 
    int len; 

    if (as == NULL) 
     return ; 
    i = 0; 
    len = ft_tablen(*as); 
    while (i < len) 
    { 
     if (*as[i]) 
      ft_strdel(&(*as[i])); 
     i++; 
    } 
    free(*as); 
    *as = NULL; 
    return ; 
} 

size_t  ft_tablen(char **tab) 
{ 
    size_t i; 

    i = 0; 
    while (tab[i]) 
     i++; 
    return (i); 
} 

Примечание: Функция ft_strdel используется в ft_tabdel освобождает строку, которая была динамически выделяемый, и устанавливает указатель на NULL. Я использую его в течение нескольких месяцев в нескольких проектах, и он еще не подвел меня.

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

спасибо.

+0

[не отбрасывают таНос] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar

+0

Помимо ответа Barmar (в которой с Я согласен), (1) использовать 'memset' для установки целых диапазонов в 0, (2) использовать' for' циклы вместо тех, которые 'x = 0, while (x <..) x ++;'; они сделаны для этого. – usr2564301

+1

@Jongware, (1) Я обновляю свой код в соответствии с этим советом. (2) Я бы, но я не могу. Этот проект предназначен для школы, и мы вынуждены соблюдать некоторые ограничения, некоторые из которых не являются петлями, максимум 25 строк на каждую функцию. Я предполагаю, что это должно научить нас писать сжатый код и не стесняться разбивать функции, чтобы наш код был как можно короче и читабельнее.Или, может быть, просто порвать с нашими головами из-за причин = P – kRYOoX

ответ

4

Вы не выделяете достаточно места.

if (!(mem = (char **)malloc(size + 1))) 

только выделяет size+1 байт. Но вам нужно выделить место для указателей size+1, а указатели, как правило, 4 байта. Вам нужно умножить число элементов на размер каждого элемента:

if (!(mem = malloc((size + 1) * sizeof(*mem)))) 
+0

Это действительно исправило крах при запуске. Я знал, что делаю глупую ошибку ... Спасибо, сэр. Я дам тесту немного больше для предложений по другим вопросам. – kRYOoX

1

В коде

char **mem; 
while (i < size + 1) 
{ 
    mem[i] = NULL; 
    i++; 
} 

мем является «указатель на указатель на гольца» и, следовательно, его размер является то, что указателя, а не символа. Когда вы говорите mem [i] и вложение i, вы увеличиваете размер указателя, а не символа, и поэтому перезаписываете память за пределами выделенной памяти. Попробуйте:

if (!(mem = (char **)malloc((size + 1)*sizeof(void *))))