LINUX.ORG.RU

Освобождение ресурсов при ошибке

 


4

5
int func(int x)
{
  char * c1 = malloc(SOMESIZE);
  char * c2 = malloc(EVENMORE);

  if ((!c1) || (!c2))
  {
    if (c1) free(c1);
    if (c2) free(c2);
    return E_CANTMALLOC;
  }

  int boolerr = 0;
  int retcode = 0;

  switch (x)
  {
  case 0:
     ...
     if (somebadnews)
     {
        boolerr = 1;
        retcode = E_CODE_GREEN;
     }
     break;
  case 1:
     ...
     if (somebadnews)
     {
        boolerr = 1;
        retcode = E_CODE_YELLOW;
     }
     break;
  case 2:
     ...
     if (somebadnews)
     {
        boolerr = 1;
        retcode = E_CODE_RED;
     }
     break;
  case 3:
     ...
     if (somebadnews)
     {
        boolerr = 1;
        retcode = E_CODE_BLACK;
     }
     break;
  default:
     boolerr = 1;
     retcode = E_CODE_BROWN;
  }

  if (boolerr)
  {
    free(c1);
    free(c2);
    return retcode;
  }

  ...

  return 0;
}

А как по канону нужно обрабатывать ситуацию, когда одна из подпрограмм вернула ошибку и нужно освободить ресурсы и передать наверх тот же код?

★★

Последнее исправление: cetjs2 (всего исправлений: 1)

Ответ на: комментарий от arturpub

Не уловил. Имеешь ввиду, можно не париться и писать...

А надо помнить нить разговора. С чего разговор начался? free(ptr) писать можно, а что писать на open()?

Дак вот я тебе говорю, что все обратные функции принимаю и обрабатывают инвалидный return от прямых функций.

int fd0 = -1, fd1 = -1; 
fd0 = open(), fd1 = open();
...
cleanup:
close(fd0), close(fd1);

... потому что -1 проскочит сквозь этот блок нопом? Или не то?

И так можно. Если у тебя нет побочных эффектов, а сисколы с -1 их не порождают, то у тебя функция просто «ничего» не сделает.

poll/select/aio/etc?

Да. Добавишь -1 - тебе вернёт «бадфд», даже можешь не проверять - у тебя просто не будет этой фдешки в следилке. Если же эта фдешка жизненно важна для тебя - exit() тебя спасёт.

Если же эта фдешка важна, но не жизненно - тебе один хрен надо будет это как-то обработать. Проще всего это сделать убив всё после местах х, после чего прыгнув на него. Можешь сохранить контекст - т.к. все побочные эффекты ты запомнил и откатил до перехода - это работает.

Carb_blog3
()
		Chapter 7: Centralized exiting of functions

Albeit deprecated by some people, the equivalent of the goto statement is
used frequently by compilers in form of the unconditional jump instruction.

The goto statement comes in handy when a function exits from multiple
locations and some common work such as cleanup has to be done.  If there is no
cleanup needed then just return directly.

The rationale is:

- unconditional statements are easier to understand and follow
- nesting is reduced
- errors by not updating individual exit points when making
    modifications are prevented
- saves the compiler work to optimize redundant code away ;)

int fun(int a)
{
	int result = 0;
	char *buffer = kmalloc(SIZE);

	if (buffer == NULL)
		return -ENOMEM;

	if (condition1) {
		while (loop1) {
			...
		}
		result = 1;
		goto out;
	}
	...
out:
	kfree(buffer);
	return result;
}

https://www.kernel.org/doc/Documentation/CodingStyle

geks
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.