Всех приветствую. вопрос по С интересно следующее как правильнее обрабатывать ошибки аргументы за тот или иной способ выслушаются с удовольствием 1 Код (Text): retcode ubzd4guwedudy(argtype this) { file_t file; thread_t thread; map_t map; file = openfile... if (!file) return ERROR_FILE_NOT_FOUND; thread = openthread... if (!thread) { closefile(file); return ERROR_ACCESS_DENIED; } map = openmap... if (!map) { closefile(file); closethread(thread); return ERROR_NOT_ENOUGH_MEMORY; } ...processing... closefile(file); closethread(thread); closemap(map); return ERROR_SUCCESS; } 2 Код (Text): retcode ubzd4guwedudy(argtype this) { file_t file = NULL; thread_t thread = NULL; map_t map = NULL; retcode retval; file = openfile... if (!file) { retval = ERROR_FILE_NOT_FOUND; goto exit; } thread = openthread... if (!thread) { retval = ERROR_ACCESS_DENIED; goto exit; } map = openmap... if (!map) { retval = ERROR_NOT_ENOUGH_MEMORY; goto exit; } retval = ERROR_SUCCESS; ...processing... exit: if (file) closefile(file); if (thread) closethread(thread); if (map) closemap(map); return retval; } 3 Код (Text): retcode ubzd4guwedudy(argtype this) { file_t file; thread_t thread; map_t map; retcode retval; file = openfile... if (file) { thread = openthread... if (thread) { map = openmap... if (map) { retval = ERROR_SUCCESS; ...processing... closemap(map); } else retval = ERROR_NOT_ENOUGH_MEMORY; closethread(thread); } else retval = ERROR_ACCESS_DENIED; closefile(file); } else retval = ERROR_FILE_NOT_FOUND; return retval; } 4 Код (Text): retcode ubzd4guwedudy(argtype this) { file_t file = NULL; thread_t thread = NULL; map_t map = NULL; retcode retval; __try { file = openfile... if (!file) { retval = ERROR_FILE_NOT_FOUND; __leave; } thread = openthread... if (!thread) { retval = ERROR_ACCESS_DENIED; __leave; } map = openmap... if (!map) { retval = ERROR_NOT_ENOUGH_MEMORY; __leave; } retval = ERROR_SUCCESS; ...processing... } __finally { if (file) closefile(file); if (thread) closethread(thread); if (map) closemap(map); } return retval; }
у меня имхо такое если 4 - ое не рассаматривать из за того что пишется что то кросплатформенное тогда остается 1 - ое 2 - ое и 3 - е дальше 1 - ое тоже можно не рассматривать кому захочется копипастить код пачками тогда остается только goto или много вложенных if'ов я очень не люблю много вложенных if'ов из за того что код начинает выезжать за правый край страницы поэтому я бы выбрал именно 2 можно ответить разбей функцию на две и не будет много вложенных if'ов но зачем ее разбивать если это логически законченная единица не требующая разбиения только для того что бы не пользоватся goto ? или смирится с тем что часть кода по мере вложения if'ов уедет за правый край страницы ?
можно так Код (Text): retcode ret = ERROR_SUCCESS; do { if(...) { ret = ...; break; } //... if(...) { ret = ...; break; } //... }while(0); if(ret != ERROR_SUCCESS) { //... } return ret;
wsd Из-за goto? Помнится в прошлом году был семинар для разработчиков от HP, так вот там они говорили что goto - хорошо и он полезен.
здоровый jmp вне закона? господа, будьте честны с собой, когда вы говорите такие вещи, вам не становится немножко стыдно, или грустно, или забавно?
Интересно, чем это умеренное использование goto всех напрягает, подобная схема (2) в ядре линукса много где юзается... Уж лучше goto чем лесенки с 12-ю уровнями вложенности...
Да и не только в линуксе, посмотрите любой пример из MSDN с использованием COM-интерфейсов. Одни goto.
если каком-то ЯВУ нет адекватной замены goto, остается использовать goto конечно RAII + эксепшены лучше, только в Си этого нет
wf_ это ядро ни когда не было и не будет расшарено, потому что у создателя не излечимая ПАРАНОЯ, что везде одни недоброжелатели и доверять можно только себе))) может это патология, но кой где видел мнения что это национальные особенности (( так что это вопрос к его единоличному архитектору GoldFinch скажи это Кенту Бекку и запости ответ)
Кому не нравятся goto, можно использовать макросы: Код (Text): #include "stdafx.h" #include "Epvolume.h" HWND g_hDlg = NULL; GUID g_guidMyContext = GUID_NULL; static IAudioEndpointVolume *g_pEndptVol = NULL; static BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM); #define EXIT_ON_ERROR(hr) \ if (FAILED(hr)) { goto Exit; } #define ERROR_CANCEL(hr) \ if (FAILED(hr)) { \ MessageBox(hDlg, TEXT("The program will exit."), \ TEXT("Fatal error"), MB_OK); \ EndDialog(hDlg, TRUE); return TRUE; } //----------------------------------------------------------- // WinMain -- Registers an IAudioEndpointVolumeCallback // interface to monitor endpoint volume level, and opens // a dialog box that displays a volume control that will // mirror the endpoint volume control in SndVol. //----------------------------------------------------------- int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HRESULT hr = S_OK; IMMDeviceEnumerator *pEnumerator = NULL; IMMDevice *pDevice = NULL; CAudioEndpointVolumeCallback EPVolEvents; if (hPrevInstance) { return 0; } CoInitialize(NULL); hr = CoCreateGuid(&g_guidMyContext); EXIT_ON_ERROR(hr) // Get enumerator for audio endpoint devices. hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); EXIT_ON_ERROR(hr) // Get default audio-rendering device. hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); EXIT_ON_ERROR(hr) hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&g_pEndptVol); EXIT_ON_ERROR(hr) hr = g_pEndptVol->RegisterControlChangeNotify( (IAudioEndpointVolumeCallback*)&EPVolEvents); EXIT_ON_ERROR(hr) InitCommonControls(); DialogBox(hInstance, L"VOLUMECONTROL", NULL, (DLGPROC)DlgProc); Exit: if (FAILED(hr)) { MessageBox(NULL, TEXT("This program requires Windows Vista."), TEXT("Error termination"), MB_OK); } if (pEnumerator != NULL) { g_pEndptVol->UnregisterControlChangeNotify( (IAudioEndpointVolumeCallback*)&EPVolEvents); } SAFE_RELEASE(pEnumerator) SAFE_RELEASE(pDevice) SAFE_RELEASE(g_pEndptVol) CoUninitialize(); return 0; } //----------------------------------------------------------- // DlgProc -- Dialog box procedure //----------------------------------------------------------- BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HRESULT hr; BOOL bMute; float fVolume; int nVolume; int nChecked; switch (message) { case WM_INITDIALOG: g_hDlg = hDlg; SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_SETRANGEMIN, FALSE, 0); SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_SETRANGEMAX, FALSE, MAX_VOL); hr = g_pEndptVol->GetMute(&bMute); ERROR_CANCEL(hr) SendDlgItemMessage(hDlg, IDC_CHECK_MUTE, BM_SETCHECK, bMute ? BST_CHECKED : BST_UNCHECKED, 0); hr = g_pEndptVol->GetMasterVolumeLevelScalar(&fVolume); ERROR_CANCEL(hr) nVolume = (int)(MAX_VOL*fVolume + 0.5); SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_SETPOS, TRUE, nVolume); return TRUE; case WM_HSCROLL: switch (LOWORD(wParam)) { case SB_THUMBPOSITION: case SB_THUMBTRACK: case SB_LINERIGHT: case SB_LINELEFT: case SB_PAGERIGHT: case SB_PAGELEFT: case SB_RIGHT: case SB_LEFT: // The user moved the volume slider in the dialog box. SendDlgItemMessage(hDlg, IDC_CHECK_MUTE, BM_SETCHECK, BST_UNCHECKED, 0); hr = g_pEndptVol->SetMute(FALSE, &g_guidMyContext); ERROR_CANCEL(hr) nVolume = SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_GETPOS, 0, 0); fVolume = (float)nVolume/MAX_VOL; hr = g_pEndptVol->SetMasterVolumeLevelScalar(fVolume, &g_guidMyContext); ERROR_CANCEL(hr) return TRUE; } break; case WM_COMMAND: switch ((int)LOWORD(wParam)) { case IDC_CHECK_MUTE: // The user selected the Mute check box in the dialog box. nChecked = SendDlgItemMessage(hDlg, IDC_CHECK_MUTE, BM_GETCHECK, 0, 0); bMute = (BST_CHECKED == nChecked); hr = g_pEndptVol->SetMute(bMute, &g_guidMyContext); ERROR_CANCEL(hr) return TRUE; case IDCANCEL: EndDialog(hDlg, TRUE); return TRUE; } break; } return FALSE; }
google ) Код (Text): #define FINALLY_ON_TRUE(expr, retvalue) \ do { if (expr) { retval = retvalue; __leave; } } while (0) retcode ubzd4guwedudy(argtype this) { file_t file = NULL; thread_t thread = NULL; map_t map = NULL; retcode retval; __try { file = openfile... FINALLY_ON_TRUE(!file, ERROR_FILE_NOT_FOUND); thread = openthread... FINALLY_ON_TRUE(!thread, ERROR_ACCESS_DENIED); map = openmap... FINALLY_ON_TRUE(!map, ERROR_NOT_ENOUGH_MEMORY); retval = ERROR_SUCCESS; ...processing... } __finally { if (file) closefile(file); if (thread) closethread(thread); if (map) closemap(map); } return retval; }
Товариши, что с вами? Зачем так отрыватся от корней? Код (Text): if(!(file=openfile)) { retVal = ERROR_FILE_NOT_FOUND; goto out; } if (!(map=openmap)) { retVal = ERROR_ACCESS_DENIDED; goto free_file; } free_file: close(file) out: return;