2013-06-04 2 views
1

Вопрос, который я не мог найти в Интернете. У меня есть этот маленький кусочек C-кода, работающего на дистрибутиве Linux хриплый (Raspberry Pi, но тот не имеет значения):free() буфер, потребляемый системой()

void function(const char * command) 
{ 

    // Define commands for in between parameters 
    char commandPre[] = "echo "; 

    // Get the lengths of the strings 
    int len= strlen(command) + strlen(commandPre); 


    // Allocate the command 
    char * fullCommand = (char *) malloc(len * sizeof(char)); 

    // Build the command 
    strcat(fullCommand, commandPre); 
    strcat(fullCommand, command); 


    // Execute command 
    system(fullCommand); 

    // Free resources 
    free(fullCommand); 
} 

Теперь я бегу этот кусок кода из программы-демона. Но когда он достигает свободного (fullCommand) во второй раз (когда функция вызывается во второй раз в моей программе), программа выходит из строя и существует. Когда я удаляю бесплатный (fullCommand), он работает так, как ожидалось.

Мой вопрос: ли система() уже освобождает «fullCommand» для меня? Если да, то почему он работает во второй раз, а не в первый раз? Я что-то упустил?

P.S. Фактически команда состоит из нескольких строк strcat'ed вместе, но выше код в его самой базовой форме

ответ

3

У вас есть переполнение буфера, поскольку вы не выделяете пространство для терминатора строк.

Также, don't cast the return value of malloc(), и проверьте возвращаемое значение, прежде чем считать выполненное распределение.

Кроме того, как вы указываете в своем собственном ответе, использование strcat() в недавно выделенном буфере сломано, так как буфер не будет пустой строкой. Извините, что не выбрал это раньше.

+0

Ах СПРАВА, глупо глупый глупый я * бьет головой *. Благодаря! Я программировал C# какое-то время, и я полностью забыл о терминаторе. Кроме того, я всегда делаю это так, потому что это быстро, но проверка возвращаемого значения - лучшая практика, спасибо за подсказку! – Maarten

+0

@Maarten «Быстро»? Он не может быть быстрее (набирать, я предполагаю, что вы имеете в виду), чем * не * набирать бросок, не так ли? Разница в производительности отсутствует, и приведение не является «хуже», чем проверка возвращаемого значения, это совершенно разные вещи. Приведение будет счастливо преобразовать NULL в указатель символа, а затем все сломается. – unwind

-1

Я нашел ошибку:

// Allocate the command 
    char * fullCommand = (char *) malloc(len * sizeof(char)); 

    // Build the command 
    strcat(fullCommand, commandPre); 

Там нет никакой гарантии, что fullCommand пуста после таНоса. strcat помещает первый символ второго аргумента вместо первого терминатора аргументов. Тем не менее, терминатор может или не может отображаться в первом местоположении выделенного массива, поскольку данные в памяти после того, как malloc является случайным. Фиксированный его, выполнив:

// Allocate the command 
char * fullCommand = calloc(len, sizeof(char)); 

С другой стороны, я мог бы сделать:

// Allocate the command 
char * fullCommand = malloc(len * sizeof(char)); 
fullCommand[0] = '\0'; 

Или ALS Alk отметил в комментариях, начните с зЬгсру:

// Allocate the command 
char * fullCommand = malloc(len * sizeof(char)); 

// Build the command 
strcpy(fullCommand, commandPre); 
+0

Или вы могли бы просто использовать 'strcpy()' вместо первого вызова 'strcat()'. – alk

+0

Ваш последний пример вызывает утечку памяти, так как вы теряете адрес, возвращаемый 'malloc()', переписывая его адресом '' ''. Вы, возможно, означали 'fullCommand [0] = '\ 0''. – alk

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