2014-12-19 2 views
0

Мне нужно нарисовать строку символов, сколько захочу. Поэтому я написал функцию для этой цели:strcat make crash program (0xc0000005)

void fDrawLine(int length) 
{ 
    int i; 
    char * compLine = (char *) malloc(WINDOW_WIDTH + 2); 

    for(i = 0; i < length; i++) 
     strcat(compLine, "-"); 

    fDrawSpacedMessage(compLine, -1, TRUE); 
} 

WINDOW_WIDTH определяется как 80, fDrawSpacedMessage другая функция для печати текстов по центру и т.д.

Он не строит отлично, никаких ошибок, никаких предупреждений. Но во время выполнения все работает, но если выполняется fDrawLine, программа вылетает и выдает код ошибки 0xc0000005. Я знаю, что это касается распределения памяти, но я уже инициализирую строку compLine.

Я пробовал пару вещей; Я думал, что другая функция вызвала это, поэтому я выделил fDrawLine, но сбой продолжался. Изменение инициализации с помощью compLine[0] = 0;, compLine[WINDOW_WIDTH] = {0}; не помогло.

Он хорошо работает с моей другой машиной, которая запускает Ubuntu с последним gcc, но при использовании Code :: Blocks (MinGW) в Windows он продолжает сбой.

Что не так с этим кодом?

+1

Почему вы не используете 'memset' заполнить«-»? И что такое значение 'length'? – i486

+0

Поскольку это школьный проект, вы, по-видимому, учитесь кодировать. Остальные вещи в стороне, посмотрите на свою функцию, затем ответьте на этот вопрос: что бы вызвал вызов 'fDrawLine (WINDOW_WIDTH * 2),' на самом деле? Научитесь программировать оборонительно – kdopen

+0

1) Нужно застраховать 'length' не слишком велико. Добавьте 'assert (length <(WINDOW_WIDTH + 1));' 2) '2' здесь магическое число. Предоставьте подробную информацию о 2? (Может ли 'fDrawSpacedMessage()' провалиться при попытке отобразить 81 длинный? ---...---??) – chux

ответ

1

Описанная память начинается с мусора. Установите его в пустую строку, например так:

compLine[0] = '\0'; 
+1

Он сказал, что это не помогло. – i486

+2

Там могут быть и другие ошибки. Поскольку мы не видели полного, но минимального примера, который все еще показывает проблему, трудно сказать. –

1

Не объявляйте compLine как указатель, так как вам не нужно, а на самом деле у вас есть утечка памяти в вашей функции, сначала объявить compLine таким образом

char compLine[1 + WINDOW_WIDTH] = {0}; // strings need an extra byte at the end to mark the end. 

затем использовать memset установить '-' характер, как этот

memset(compLine, '-', length); 

конечно, проверить т шляпа length <= WINDOW_WIDTH.

Это ваша функция фиксирована, так что вы можете попробовать это

void fDrawLine(int length) 
{ 
    char compLine[1 + WINDOW_WIDTH] = {0}; // initialized so that last byte is '\0'. 
    if (length > WINDOW_WIDTH) 
     length = WINDOW_WIDTH; 
    memset(compLine, '-', length);   
    fDrawSpacedMessage(compLine, -1, TRUE); 
} 

помимо использования strcat что путь плохая идея, вы можете это сделать это

char *compLine = malloc(1 + length); // the last extra '\0' byte. 
if (compLine == NULL) // malloc returns NULL on failure to allocate memory 
    return; // so we must abort this function in that case. 
for(i = 0; i < length; i++) 
    compLine[i] = '-'; 
compLine[length] = '\0'; 

fDrawSpacedMessage(compLine, -1, TRUE); 
free(compLine); 

вы также можете использовать memset в этот случай, и это на самом деле лучше.

+1

Здесь нет большой разницы в производительности, но в первом примере лучше вручную установить 'compLine [length]' to '\ 0', а не инициализировать весь массив как' 0 's. – HolyBlackCat

+1

, возможно, но это хорошая привычка для новых программистов инициализировать это так, поскольку они часто забывают о завершающем '' \ 0'', это, безусловно, самая распространенная ошибка, которую я видел. Я, конечно, ошибаюсь. Некоторые могут даже привыкнуть к 'calloc', чтобы избежать этой проблемы. –

+3

Если они забудут о завершении «\ 0», они забудут об инициализации всего массива. Удивительно, как многие разработчики тратят циклы на инициализацию больших буферов, прежде чем загружать их в следующую строку. –

0

Есть несколько проблем с вашим кодом ниже

void fDrawLine(int length) 
{ 
    int i; 
    char * compLine = (char *) malloc(WINDOW_WIDTH + 2); 

    for(i = 0; i < length; i++) 
     strcat(compLine, "-"); 

    fDrawSpacedMessage(compLine, -1, TRUE); 
} 

Первый параметр length должен быть по крайней мере unsigned int как отрицательная длина не имеет смысла. В идеале вы должны использовать size_t. То же самое касается i.

Затем вы не защищаете себя от недопустимых значений для length. Неявный контракт заключается в том, что 0 < = length < = WINDOW_WIDTH - укажите его.

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

И, наконец, strcat является излишним, чтобы добавить один символ.

Взяв все это вместе, вот альтернативная реализация.

void fDrawLine(size_t length) 
{ 
    size_t actual_length = length <= WINDOW_WIDTH ? length : WINDOW_WIDTH; 
    char compLine[WINDOW_WIDTH+2]; 

    memset(compLine, '-', actual_length); 
    compline[actual_length] = '\0'; 
    fDrawSpacedMessage(compLine, -1, TRUE); 
} 

Я оставил compline в WINDOW_WIDTH+2, как я предполагаю, fDrawSpacedMessage добавляет символ новой строки.

Если он по-прежнему падает, проблема в fDrawSpacedMessage

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