我正在用 C 撰寫一個簡單的實用程式,并且正在撰寫代碼以在 STDERR 中列印錯誤訊息。
我有一個結構,定義為:
struct arguments
{
FILE *source;
int modifier_value;
int filesize;
};
我已經宣告了一個指向上述結構的指標,并為其分配了記憶體:
struct arguments *arg = NULL;
arg = malloc(sizeof(struct arguments));
if(arg == NULL)
{
fprintf(stderr, "error: malloc - %s\n", strerror(errno)); //I know i could use perror as well, but I like the convention of using fprintf() for both stdout, stderr, and other file streams, just for symmetry
return EXIT_FAILURE;
}
如您所見,我只分配了足以存盤一個型別物件的記憶體struct arguments,但我仍然對其進行錯誤檢查。
問題是我有很多指標,比如指向一個物件空間的指標,對所有這些指標進行錯誤檢查只會增加代碼數量并影響代碼的可讀性。
如果我只是因為我沒有分配太多記憶體而忽略錯誤檢查,這是一個“好的做法”/“可以嗎” (我聽說過一些關于分頁的事情,我認為如果我請求太多,系統會合并很多頁面在這種情況下,很多記憶體和出錯的可能性會很高,但對于 64 位元組之類的記憶體請求則不然)。
uj5u.com熱心網友回復:
如果我只是因為我沒有分配太多記憶體而忽略錯誤檢查,這是一個“好的做法”/“可以嗎”
不對報告錯誤的函式呼叫進行錯誤檢查是不好的做法,除非您不關心呼叫是否成功。而且你總是關心是否malloc()成功,否則你不應該首先呼叫它。malloc()除非檢查呼叫是否成功,否則您不知道是否分配了太多記憶體。
問題是我有很多指標,比如指向一個物件空間的指標,對所有這些指標進行錯誤檢查只會增加代碼數量并影響代碼的可讀性。
首先,只在真正需要的地方使用動態分配。有些人似乎有這樣的想法,他們需要在任何需要指向物件的指標的地方進行動態分配。這絕對不是這樣的。如果您正在執行動態分配,則需要指標,但在使用指標的地方不一定需要動態分配。通常,靜態或自動分配可以與尋址運算子(一元&)結合使用。例如:
{
struct arguments arg = {0};
init_arguments(&arg);
do_something(&arg);
// all done with arg
}
僅當 (i) 您在編譯時不知道需要多少記憶體,或者 (ii) 您需要一個物件,其生命周期超過包含其創建的最內層塊的終止時,才需要動態分配。
當你確實需要動態分配時,你可以通過使用宏或包裝函式來減少樣板代碼的數量。類似適用于執行其他成功檢查。例如,使用這樣的函式而不是malloc()直接使用:
void *checked_malloc(size_t size) {
void *result = malloc(size);
if (result == NULL && size != 0) {
fputs("error: malloc failed -- aborting...\n", stderr);
abort();
}
return result;
}
uj5u.com熱心網友回復:
創建分配包裝函式,以便始終檢查分配是否成功。
擴展@Weather Vane傳遞引數以識別呼叫者的想法,但在宏包裝器中進行。
my_malloc.h
#ifndef MY_MALLOC
#define MY_MALLOC(size) my_malloc((size), __FUNC__, __LINE__)
#include <stdlib.h>
// Return a valid allocation or don't return.
void *my_malloc(size_t size, const char *func, unsigned line);
#endif
my_malloc.c
#include "my_maloc.h"
#include <stdio.h>
#include <stdlib.h>
void *my_malloc(size_t size, const char *func, unsigned line) {
if (size == 0) {
return NULL;
}
void *ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Failed to allocate %zu bytes at \"%s()\", line %u\n",
size, func, line);
exit(EXIT_FAILURE);
}
return ptr;
}
用戶代碼.c
#include "my_malloc.h"
...
// No need to explicitly pass the function name, line number
arg = MY_MALLOC(sizeof *arg * n);
// Error checking not needed.
...
free(arg);
我什至會考慮MY_FREE釋放指標和預期大小的匹配。然后這兩個例程可以保留分配統計資訊、自由大小驗證……
uj5u.com熱心網友回復:
如果你有很多物件,你可以立即為所有物件分配記憶體:
void *pvc;
pvc = malloc(how_many_for_all);
然后像這樣連續宣告指向物件的指標:
Obj1 *p1;
Obj2 *p2;
Obj3 *p3;
p1 = (Obj1)pvc;
p2 = (Obj2)(pvc sizeof(Obj1));
p3 = (Obj3)(pvc sizeof(Obj1) sizeof(Obj2));
這是更快的偽代碼。編譯器將發出警告,但這有效。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/534179.html
標籤:C分配
上一篇:C步進電機代碼表現不同1/5次
