Допустим, у меня есть функция для выполнения небольшой и конкретной задачи, которая имеет довольно высокую вероятность отказа. Каков наилучший способ справиться с чем-то, что идет не так? (если я знаю в чем проблема).
Например, скажем, у меня есть функция, которая читает двухбайтовую строку и возвращает ее:
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo = malloc(3);
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo = bar();
puts(foo);
free(foo);
return 0;
}
В приведенном выше примере нет абсолютно никакой обработки ошибок. Есть два способа реализации какой-то обработки ошибок, но я не уверен, какой из них предпочтительнее или считается лучшей практикой.
Способ 1 (распечатать сообщение об ошибке в stderr из функции):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3)))
{
fputs("\nError! Memory allocation failed.", stderr);
return 0x00;
}
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar())) return 1;
puts(foo);
free(foo);
return 0;
}
Способ 2 (распечатать сообщение об ошибке в stderr из вызывающей функции):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3))) return 0x00;
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar()))
{
fputs("\nError! Memory allocation failed.", stderr);
return 1;
}
puts(foo);
free(foo);
return 0;
}
Я почти думаю, что второй метод был бы лучшим, потому что таким образом я мог бы более точно указать свои сообщения об ошибках в зависимости от того, для чего я вызываю эту функцию в то время. Что меня беспокоит со вторым методом, так это то, что я теряю возможность печатать, что именно пошло не так в функции, если у нее есть более одной потенциальной точки отказа.
Псевдокод:
IF FAILUREA
PRINT "FAILUREA OCCURED"
RETURN
IF FAILUREB
PRINT "FAILUREB OCCURED"
RETURN
Это не было бы большой проблемой, если бы функция, которую я вызывал, была int
, потому что тогда я мог бы просто вернуть другое целочисленное значение в зависимости от того, что пошло не так. Но в случае char*
я обычно пытаюсь вернуть NULL
в случае неудачи (поэтому и FAILUREA
, и FAILUREB
будут возвращать NULL
); не было бы никакого способа узнать, что вызвало сбой функции.
Итак, мой вопрос: как лучше всего обрабатывать сообщения об ошибках?
malloc
нигде не назначает эту память... так что это утечка, несмотря ни на что... но обработка ошибок здесь довольно субъективна. Это действительно зависит от вас, где вы хотите обрабатывать ошибки (или, если вы программируете в ядре Linux, им нравится просто дать ему сбой, чтобы получить обратную трассировку!) Лично я предпочитаю позаботиться об этом в функции, в которой происходит ошибка. держать мойmain()
в чистоте, но это действительно зависит от вас. - person Mike   schedule 10.10.2012