В процессе изучения исходников одного dock app'а возник вопрос.Вот код:
mySettings.color_bg = strdup("white");
...
/* далее при обработке опций командной строки: */
case 'B': /* bgcolor */
if(optarg)
mySettings.color_bg = strdup(optarg);
else {
fprintf(stderr, "no bg-color given\n");
exit(1);
}
break;
...Вопросы следующие:
1) есть ли ошибка в том, что при использовании опции -B переменная color_bg будет инициализироваться дважды?
2) в man strdup(3) написано, что память выделяется с помощью malloc() и её можно освобождать с помощью free(). В коде нигде нет free(mySettings.color_bg), но при этом valgrind утечку не нашел. Почему?
3) зачем при инициализации используется strdup()? Почему бы просто не присвоить строку?Спасибо за разъяснения.
>В процессе изучения исходников одного dock app'а возник вопрос.
>
>Вот код:
>
>mySettings.color_bg = strdup("white");
>...
>/* далее при обработке опций командной строки: */
> case 'B': /* bgcolor */
> if(optarg)
> mySettings.color_bg =
>strdup(optarg);
> else {
> fprintf(stderr, "no
>bg-color given\n");
> exit(1);
> }
> break;
>...
>
>Вопросы следующие:
>
>1) есть ли ошибка в том, что при использовании опции -B переменная
>color_bg будет инициализироваться дважды?Вовсе не факт, если не передан параметр -B -> только единожды.
mySettings.color_bg = strdup("white");
просто банальная инициализация.
>2) в man strdup(3) написано, что память выделяется с помощью malloc() и
>её можноне МОЖНО, а НУЖНО!
> освобождать с помощью free(). В коде нигде нет free(mySettings.color_bg),
>но при этом valgrind утечку не нашел. Почему?Вестимо, потому что используется в int main(). В этом случае, когда процесс завершается система сама за него освобождает память. valgrind, насколько я могу судить исходит из расчетов (сколько выделено - сколько освобождено).
>3) зачем при инициализации используется strdup()? Почему бы просто не присвоить строку?
Керниган и Ритчи "Язык программирования Си".
>Вовсе не факт, если не передан параметр -B -> только единожды.В случае если инициализация произойдет дважды ничего страшного нет. Но ведь инициализация-то происходит с помощью ф-ции strdup(). Т.е. Сначала выделится память, потом выделится второй раз и причем после второго переприсванивания уже будет невозможно освободить память, которая выделилась при первом вызове strdup(). Т.е. эта утечка будет даже не так легко обнаруживаема :(
Но ведь если код модифицировать, то можно обойтись без переприсваивания:
mySettings.color_bg = NULL;
...
/* далее при обработке опций командной строки: */
case 'B': /* bgcolor */
if(optarg)
mySettings.color_bg = strdup(optarg);
else {
fprintf(stderr, "no bg-color given\n");
exit(1);
}
break;
...
// присваиваем дефолтное значение только если оно не было указано ранее
if (mySettings.color_bg == NULL) {
mySettings.color_bg = strdup("white");
}Подтвердите или опровергните мои размышления.
>>2) в man strdup(3) написано, что память выделяется с помощью malloc() и
>>её можно
>не МОЖНО, а НУЖНО!Спасибо. Буду тогда более внимательно за этим следить.
>> освобождать с помощью free(). В коде нигде нет free(mySettings.color_bg),
>>но при этом valgrind утечку не нашел. Почему?
>Вестимо, потому что используется в int main(). В этом случае, когда процесс
>завершается система сама за него освобождает память.Вы правы. Этот код целиком находится в main().
>>3) зачем при инициализации используется strdup()? Почему бы просто не присвоить строку?
>Керниган и Ритчи "Язык программирования Си".В процессе :)
Спасибо!
>>Вовсе не факт, если не передан параметр -B -> только единожды.
>
>В случае если инициализация произойдет дважды ничего страшного нет. Но ведь инициализация-то
>происходит с помощью ф-ции strdup(). Т.е. Сначала выделится память, потом выделится
>второй раз и причем после второго переприсванивания уже будет невозможно освободить
>память, которая выделилась при первом вызове strdup(). Т.е. эта утечка будет
>даже не так легко обнаруживаема :(Разумеется.
>Но ведь если код модифицировать, то можно обойтись без переприсваивания:
Именно. Но разработчик той софтины, исходный код, которой вы смотрите решил иначе. ИМХО, выбранный вами подход более корректен. А вообще лучше шерстить /usr/src uname==FreeBSD, ИМХО. Или исходный код postfix'a на такие моменты.
>ИМХО, выбранный вами подход более корректен.Спасибо. Приятно слышать :)
>А вообще лучше шерстить /usr/src uname==FreeBSD, ИМХО. Или исходный код postfix'a на такие моменты.
Я поглядываю /usr/src OpenBSD как самой безопасной ОС :)
Спасибо за ваши ответы, Чип! :)
>Спасибо за ваши ответы, Чип! :)welcome :)