为了简化对malloc、realloc或calloc的调用失败的处理,我创建了几个文件来规定“安全”内存管理。这是我的项目stac的一部分,因此前缀将出现在下面的代码段中。此外,我决定使用snake_case而不是标准camelCase。
我希望从中得到什么,以及我所面临的问题:这些功能是否存在于错误的实践中?是否有一种不同的方式来处理对内存分配器的失败调用?我写的代码有什么特别的错误吗?
#include "safe_mem.h"
void* safe_malloc(size_t size){
void* memory = malloc(size);
if(memory == NULL){
free(memory);
runtime_error("failed to allocate memory.");
}
return memory;
}
void* safe_calloc(size_t num, size_t size){
void* memory = calloc(num, size);
if(memory == NULL){
free(memory);
runtime_error("failed to allocate memory.");
}
return memory;
}
void* safe_realloc(void* ptr, size_t size){
void* memory = realloc(ptr, size);
if(memory == NULL){
free(memory);
runtime_error("failed to reallocate memory.");
}
return memory;
}#ifndef STAC_SAFE_MEM
#define STAC_SAFE_MEM
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
void* safe_malloc(size_t);
void* safe_calloc(size_t, size_t);
void* safe_realloc(void*, size_t);
#endif#include "error.h"
void make_error(char* type, char* message){
eprintf("%s error: %s\n", type, message);
}
void fatal_error(char* type, char* message, int exit_code){
make_error(type, message);
exit(exit_code);
}
void runtime_error(char* message){
fatal_error("Runtime", message, STATUS_RUNTIME_ERROR);
}
void generic_error(char* message){
fatal_error("Generic", message, STATUS_GENERIC_ERROR);
}#ifndef STAC_ERROR
#define STAC_ERROR
#include <stdio.h>
#include <stdlib.h>
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define STATUS_OKAY (0)
#define STATUS_RUNTIME_ERROR (1)
#define STATUS_GENERIC_ERROR (-1)
void make_error(char*, char*);
void fatal_error(char*, char*, int);
void runtime_error(char*);
void generic_error(char*);
#endif发布于 2017-06-22 22:01:45
这些功能是否存在于不良实践中?
我要说的是,只要它们正在包装的原始函数具有相同的函数签名,就可以替换它们。
我写的代码有什么特别的错误吗?
分配0字节可能返回NULL,这并不表示内存不足.
calloc(),realloc()也一样。
void* memory = malloc(size);
// if(memory == NULL){
if(memory == NULL && size > 0){在free(memory)之后调用if(memory == NULL)没有意义
if(memory == NULL){
// free(memory);对于eprintf(...),考虑传递错误源的__FUNC__、__LINE__以帮助调试。或者至少创建唯一的错误消息。
void* safe_malloc(size_t size){
runtime_error("failed to malloc memory.");
void* safe_calloc(size_t num, size_t size){
runtime_error("failed to calloc memory.");在几个地方,使用const可以更广泛地应用不改变引用数据的函数。
// void make_error(char* type, char* message){
void make_error(const char* type, const char* message){我不喜欢你的名字-空间选择error.h,其中包括eprintf, STATUS_OKAY, STATUS_GENERIC_ERROR, make_error, ...,如果我说这些使用在其他..c文件,我将如何被引导回error.h/error.c作为他们的起源?虽然有点冗长,但我更喜欢error_printf, ERROR_STATUS_GENERIC,...
小调:#include <stdio.h>不必出现在safe_mem.h中,#include <stdlib.h>不需要出现在error.h中。error.c应该有#include <stdlib.h>,正如它所称的exit()。error.c不应该依赖error.h,包括这一点。关于safe_mem.c的类似问题
从设计的角度来看,我还会包括void safe_free(void *),因为这些安全函数的功能可能会扩展,并且要求即使它现在什么也不做。它使safe_...()对称。
https://codereview.stackexchange.com/questions/166364
复制相似问题