From 4ec701b43e7dd4270d10e5bebb7332ded3cdb8bc Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Thu, 26 Mar 2026 16:15:10 +0100 Subject: [PATCH] Prevent a crash with shared ngspice when memory is exhausted: Add a pre-check if available memory is sufficient. If not, bail out. --- src/frontend/outitf.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 91cb49624..a9e47df3c 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -38,6 +38,11 @@ extern int EVTsetup_plot(CKTcircuit* ckt, char* plotname); extern IFsimulator SIMinfo; extern char Spice_Build_Date[]; +extern unsigned long long getMemorySize(void); +extern unsigned long long getPeakRSS(void); +extern unsigned long long getCurrentRSS(void); +extern unsigned long long getAvailableMemorySize(void); + static int beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analName, char *refName, int refType, int numNames, char **dataNames, int dataType, bool windowed, runDesc **runp); @@ -60,6 +65,7 @@ static bool getSpecial(dataDesc *desc, runDesc *run, IFvalue *val); static void freeRun(runDesc *run); static int InterpFileAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr); static int InterpPlotAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr); +static inline int vlength2delta(int len); /*Output data to spice module*/ #ifdef TCL_MODULE @@ -550,6 +556,20 @@ OUTpD_memory(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) { int i, n = run->numData; + if (!cp_getvar("no_mem_check", CP_BOOL, NULL, 0)) { + /* Estimate the required memory */ + size_t memrequ = (size_t)n * vlength2delta(0) * sizeof(double); + size_t memavail = getAvailableMemorySize(); + + if (memrequ > memavail) { + fprintf(stderr, "\nError: memory required (%Id Bytes)\n" + " is more than memory available (%Id Bytes)!\n", + memrequ, memavail); + fprintf(stderr, "Setting the output memory is not possible.\n"); + controlled_exit(1); + } + } + for (i = 0; i < n; i++) { dataDesc *d;