在这段代码中使用 goto 有什么好处?
static gboolean
gst_fd_src_start (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FD_SRC (bsrc);
src->curoffset = 0;
if ((src->fdset = gst_poll_new (TRUE)) == NULL)
goto socket_pair;
gst_fd_src_update_fd (src, -1);
return TRUE;
/* ERRORS */
socket_pair:
{
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
GST_ERROR_SYSTEM);
return FALSE;
}
}
为什么这里有人使用了goto socket_pair;
我不明白为什么使用这种机制? 为什么我们不直接在那里写入错误消息并返回?
注意:这是 gstreamer 插件代码
static gboolean
gst_fd_src_start (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FD_SRC (bsrc);
src->curoffset = 0;
if ((src->fdset = gst_poll_new (TRUE)) == NULL)
goto socket_pair;
gst_fd_src_update_fd (src, -1);
return TRUE;
/* ERRORS */
socket_pair:
{
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
GST_ERROR_SYSTEM);
return FALSE;
}
}
why here someone has used goto socket_pair;
i am not getting why this mechanism is used ?
why dont we just write error message there and return ?
note: this is gstreamer plugin code
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
在较大的例程中,函数中可能有多个点需要
转到
错误处理代码。该例程应该在根据代码约定编写的上下文中查看,该代码约定要求采用通用的错误处理形式。确实,
goto
应该被认为是危险的,但对于像 C 这样没有异常处理的语言来说,它可能是错误处理中最不坏的选择。In larger routines there might be multiple points in the function which need to
goto
the error handling code. This routine should be seen in the context of having been written according to code conventions that mandate a common form for error handling.It's true that
goto
should be considered dangerous but for a language like C which has no exception handling it can be the least bad option for error handling.在您引用的代码中,基本上没有任何充分的理由。
不过,一般来说,如果函数需要在失败时执行不止一件事(例如,不仅仅是返回错误代码),或者如果编码标准每个函数都需要一个单一
返回
(某些政府工作会这样做)。然后,主体代码在需要时使用goto
触发错误处理。这有点像穷人的try/catch/finally
事情。例如:
基本上,从
acquireSomeResource()
到exit:
标签的所有内容都非常粗略地是一个try
块,exit:
标签是finally
,error_out
是 catch。非常粗略。 :-)In the code you've quoted, there basically isn't any good reason for it.
In general, though, you'll sometimes see an "error handling" label at the bottom of a function if the function needs to do more than one thing on failure (e.g., not just returning an error code), or if the coding standards require a single
return
for every function (some government work does this). The main body code then usesgoto
to trigger the error handling when it needs to. This is sort of a poor man'stry/catch/finally
thing.So for instance:
There, basically everything from
acquireSomeResource()
through to theexit:
label is very roughly atry
block, theexit:
label is thefinally
, and theerror_out
is the catch. Very roughly. :-)如果这是在老式 C 语言中,它没有作为语言结构内置异常处理,那么这个习惯用法是模拟它的好方法。
假设有 10 个提前退出条件。如果您想将每个代码都编码为 return 语句,则必须重复调用 GST_ELEMENT_ERROR 10 次,而使用 goto 意味着您只需将其放置一次。
显然,在这种情况下,只有 1 个提前退出条件,但通常最好通过代码一直实现此习惯用法,而不是仅在严格需要它的函数中实现
if this is in old fashioned C which doesn't have exception handling built in as a language structure, this idiom is a good way to simulate it.
imagine there were 10 early exit conditions. if you wanted to code each one as a return statement you would have to repeat the call to GST_ELEMENT_ERROR 10 times, whereas using the goto means you only need to put it once.
obviously in this case there is only 1 early exit condition but it's usually better to implement this idiom all the way through the code rather than only in functions that strictly need it
这是 C 语言中将错误处理和清理与正常代码分开的常见方法。在其他语言中,您将使用某种结构化异常。这是用 C 语言实现的更简洁的方法。在更复杂的情况下,好处更明显。在许多情况下,必须从不同的地方调用错误处理/清理代码。重构它没有多大意义,我认为如果您因此在 C 中使用
goto
并没有那么邪恶。在其他具有更好机制的编程语言中,您当然应该避免使用goto
...This is a common way in C to separate the error handling and cleaning up from the normal code. In other languages you would use some kind of structured exception instead. This is a cleaner way to do it in C. In more complex situations the benefit is more visible. In many cases the error handling/cleanup code would have to be called from different places. Refactoring it does not make much sense I think that
goto
is not that evil if you use it in C for that sake. In other programming languages having better mechanisms, you should of course avoid the use ofgoto
...这样做可以具有用于处理套接字错误的通用代码。在这种特殊情况下,仅在一种情况下需要,并且在这种情况下可能不需要使用 goto,但只是出于一致性原因(所有代码库的通用方法)。
This may be done to have common code for processing socket error. In this particular case is needed only in one case and there might be no need to use goto in this case, but only for consistency reasons (general approach for all code base).
如上所述,如果你只看这个功能,那是没有意义的。然而,如果你的函数有很多错误情况,并且在退出函数之前有一些清理问题,这种编程是不可避免的,否则你的代码将会因所有错误问题或一些清理问题而增加。为了使编程更加结构化,有时所有函数都可以用 goto 析构函数编写,就像您提到的代码一样。
As mentioned above if you look only this function, it is meaningless. However if you have a function with many error situations and with some cleaning issues before exiting function, this kind of programming is inevitable, otherwise your code will increase for all error issues or some cleaning issues. To make programming more structural, sometimes all functions could be written with goto destructor, like the code you mention.
正如其他答案中指出的那样,它在简单的示例中没有多大作用;当需要获取多种资源和多种错误情况时,它的好处更加明显。此伪代码演示了这一点:
请注意,从外部看,上述函数如何以原子方式工作 - 当它返回时,要么分配所有资源,要么不分配任何资源,从而避免泄漏。
将此版本与使用嵌套而不是 goto 的一个可能版本进行比较:
该版本更难阅读。在 goto 版本中,乍一看主要执行路径是什么是显而易见的;在这里'它不是。嵌套使代码更难以阅读,并且还浪费了水平空间。
希望我没有搞砸它,它在功能上等同于 goto 示例;我建议你尝试证明它是等价的,并亲眼看看它的工作有多困难。
As was pointed out in other answers, it doesn't do much in the simple example; its benefits are more apparent when there are multiple resources to aquire, and multiple error conditions. This pseudocode demonstrates this:
Note how the above function works atomically as seen from the outside - when it returns, either all resources are allocated, or none of them, avoiding leaks.
Compare this to one possible version that uses nesting instead of goto:
This version is much harder to read. In the goto version, it's obvious at first look what the primary execution path will be; here' it is not. The nesting makes code harder to read and also wastes horizontal space.
Hopefully I didn't mess it up and it's functionally equivalent to the goto example; I suggest you try to prove yourself that it is equivalent, and see for yourself how harder it is to work with.
goto 没有任何优点(除了退出嵌套循环)。有些人可能会说这里的错误处理与逻辑是分离的。但我会把它写成:
goto has no advantages (except exit nested loops). Some people may argue that here error-handling is separated form logic. But i whould write it as: