我正在开发一个 Python C 项目,该项目涉及一些动态分配的结构,例如队列和线程结构。我主要是想提高可读性。它看起来像这样:
#include <Python.h>
#include <stdlib.h>
typedef struct Queue;
typedef struct Control;
typedef struct Logging;
typedef struct Args;
void cleanupQueue(Queue *q);
void cleanupControl(Control *c);
void cleanupLogging(Logging *l);
void cleanupArgs(Args *a);
static PyObject *pycalledfunction(){
Queue *queue = (Queue *) malloc(sizeof(Queue));
if(!queue){
PyErr_SetString(type, message);
return NULL;
}
// initialize queue and fill
Control *control = (Control *) malloc(sizeof(Control));
if(!control){
cleanupQueue(queue);
PyErr_SetString(type, message);
return NULL;
}
// initialize control
Logging *logging = (Logging *) malloc(sizeof(Logging));
if(!logging){
cleanupControl(control);
cleanupQueue(queue);
PyErr_SetString(type, message);
return NULL;
}
// initialize logging
Args *args = (Args *) malloc(sizeof(Args));
if(!logging){
cleanupLogging(logging);
cleanupControl(control);
cleanupQueue(queue);
PyErr_SetString(type, message);
return NULL;
}
// initialize and fill args with the other structs
// Note: I guess I could check if they all exist before doing work with them here but I was unsure if that is a good practice since I am loading them into the args and am keen on getting the correct error message.
// bunch of work here
cleanupQueue(queue);
cleanupControl(control);
cleanupLogging(logging);
cleanupArgs(args);
return obj;
}
现在,只要正确清理分配的内存,这段代码就可以正常工作;尽管它稍微降低了代码的流程及其整体可读性,但我仍然希望在一定程度上改进我的结构化实践。我在那里留下了一张便条,标记我可以在做任何工作之前检查每个结构(将所有检查放在同一个地方),但我觉得这会导致相同的流程。
有什么方法可以确保在改进代码结构的同时返回正确的错误吗?
您可以拿出好的 ol'
goto
(这是 goto
的一个有效用例):
PyObject *main()
{
Queue *queue = malloc(sizeof *queue);
if (!queue){
goto fail_queue;
}
Control *control = malloc(sizeof *control);
if (!control){
goto fail_control;
}
Logging *logging = malloc(sizeof *logging);
if (!logging){
goto fail_logging;
}
Args *args = malloc(sizeof *args);
if (!args){
goto fail_args;
}
cleanupQueue(queue);
cleanupControl(control);
cleanupLogging(logging);
cleanupArgs(args);
return obj;
fail_args:
cleanupLogging(logging);
fail_logging:
cleanupControl(control);
fail_control:
cleanupQueue(queue);
fail_queue:
PyErr_SetString(type, message);
return NULL;
}
我的标签可能不够有创意,请随意重命名。