2014-10-18 2 views
2

Хорошо, я приложил много усилий, рассмотрел здесь много вопросов, но я не могу дойти до сути этого. Надеюсь, вы можете пролить свет на мою проблему здесь!malloc() повторное использование местоположения памяти после free(), вызывающее фрагментацию (?)

int main(int argc, char *argv[]){ 

    char read[50]; 
    char *string[10]; 

    while(1){ 

    fgets(read,sizeof read, stdin); 

    int t = 0; //ticks whenever a non-whitespace char is read 
    int pos = 0; //keeps track of position in string array 
    int i; 
    int j; 

    for(i = 0; i < sizeof read; i++){ 
     if(isspace(read[i]) && t != 0){ 
     string[pos] = malloc((t+1) * (sizeof(char))); 
//  int z; 
//  for(z = 0; z < sizeof string[pos]; z++){ 
//  string[pos][z] = '\0'; 
//  } 
     for(j = 0; j < t; j++){ 
      string[pos][j] = read[i-(t-j)]; 
     } 
     t = 0; 
     pos++; 
     } 
     else if(!isspace(input[i])) t++; 
    } 

    int k; 
    for(k = 0; k < pos; k++){ 
     printf("%i: %s\n",k,string[k]); 
     free(string[k]); 
    } 
    } 
} 

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

Я использую malloc() для выделения достаточного количества памяти для каждого слова, освобождая его после использования.

Первый прогон в порядке, но после последующих циклов слова короче 5 символов (и только если набрано более одного слова, разделенное пробелом) не будет отображаться правильно, со случайными дополнительными символами/символами, добавленными к ним ,

Возможно, это связано с тем, что malloc использует свободную память, которая не пуста? Если это так, как я должен правильно использовать malloc?

Единственный способ исправить это - использовать код, который я прокомментировал. Он заполняет вновь выделенный массив символов с помощью \ 0.

Спасибо!

пример вывода:

input words(0): we we we 
0: we 
1: we 
2: we 

input words(1): we we we 
0: we� 
1: we� 
2: we 
+0

является calloc не полезной функцией здесь? http://stackoverflow.com/questions/1538420/difference-between-malloc-and-calloc –

+0

Да, 'malloc' попытается повторно использовать как можно больше памяти для удобства кэширования. – o11c

+0

Кажется, calloc() мог бы быть полезен, если бы я не заполнил весь массив сразу - в моем случае, обнуление последнего байта, похоже, решило мою проблему! – Hal

ответ

6

У вас есть две проблемы:

1) Вы используете sizeof read в состоянии здесь:

for(i = 0; i < sizeof read; i++){ 

Что делать, если входная строка была не так долго, как sizeof read? Здесь вы должны использовать strlen(read).

2) Пока вы выделяете достаточное количество памяти для строки, вы не оканчиваете их на 0. Вы могли бы calloc() обнулить всю выделенную память. Так, вы сразу же писать в них, я бы предпочел использовать malloc(), а затем без необходимости обнуления с calloc() и 0-завершает строку сразу после цикла с:

for(j = 0; j < t; j++){ 
     string[pos][j] = read[i-(t-j)]; 
    } 
    string[pos][j] = 0; // 0 terminates the string. 

PS: sizeof(char) всегда 1.

+0

Отлично, завершение строки, похоже, решило это! Хороший совет на strlen() тоже, я воспользуюсь этим. Спасибо! – Hal

1

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

Все строки (c-style) должны заканчиваться завершающим символом 0, если вы этого не сделаете, то, что вы получаете, является неопределенным поведением.

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

AVOID undefined поведение.

+0

Спасибо, я не знал, что malloc() имел такое поведение, это очень полезно знать. – Hal