Yalantis/uCrop · error · CImgArgumentException
cimg::tic(): Too much calls to 'cimg::tic()' without calls t
Error message
cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'.
What it means
cimg::tic()/toc() implement a LIFO stack of timers with a fixed-capacity internal buffer. Each tic() pushes a start timestamp; if you call tic() more times than the stack capacity (CImgDebug/stack size, default 64) without matching toc() calls, pos exceeds the buffer width and CImg throws CImgArgumentException to prevent a stack overflow.
Source
Thrown at ucrop/src/main/jni/CImg.h:70189
cimg_snprintf(command,command._width,"%s.gz",filename_local);
std::rename(command,filename_local);
}
}
return filename_local;
}
// Implement a tic/toc mechanism to display elapsed time of algorithms.
inline cimg_uint64 tictoc(const bool is_tic) {
cimg::mutex(2);
static CImg<cimg_uint64> times(64);
static unsigned int pos = 0;
const cimg_uint64 t1 = cimg::time();
if (is_tic) {
// Tic.
times[pos++] = t1;
if (pos>=times._width)
throw CImgArgumentException("cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'.");
cimg::mutex(2,0);
return t1;
}
// Toc.
if (!pos)
throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made.");
const cimg_uint64
t0 = times[--pos],
dt = t1>=t0?(t1 - t0):cimg::type<cimg_uint64>::max();
const unsigned int
edays = (unsigned int)(dt/86400000.),
ehours = (unsigned int)((dt - edays*86400000.)/3600000.),
emin = (unsigned int)((dt - edays*86400000. - ehours*3600000.)/60000.),
esec = (unsigned int)((dt - edays*86400000. - ehours*3600000. - emin*60000.)/1000.),
ems = (unsigned int)(dt - edays*86400000. - ehours*3600000. - emin*60000. - esec*1000.);
if (!edays && !ehours && !emin && !esec)
std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u ms%s\n",View on GitHub (pinned to f788b534b4)
Solutions
- Ensure every cimg::tic() has a matching cimg::toc() on all code paths, including early returns and exception handlers.
- Move tic()/toc() outside loop bodies — tic once before the loop, toc after, instead of timing each iteration.
- For deeply nested/recursive timing, store start times yourself (e.g. cimg::time() into your own vector) instead of using nested tic()/toc().
- Increase the stack capacity by recompiling with a larger cimg_tic_toc size / modifying the times buffer if you genuinely need deep nesting.
Example fix
// before
cimg_forXY(img,x,y) {
cimg::tic(); // pushes a new entry every iteration -> overflow after 64 iterations
process(img(x,y));
cimg::toc();
}
// after
cimg::tic(); // time the whole loop once
cimg_forXY(img,x,y) process(img(x,y));
cimg::toc(); Defensive patterns
Strategy: validation
Validate before calling
// Keep a running balance of tic/toc and assert it stays within capacity (default stack = 64)
static int ticDepth = 0;
#define SAFE_TIC() do { if (ticDepth >= 64) { fprintf(stderr,"tic overflow\n"); } else { cimg::tic(); ++ticDepth; } } while(0)
#define SAFE_TOC() do { if (ticDepth > 0) { cimg::toc(); --ticDepth; } } while(0) Try / catch
try {
cimg::tic();
measure();
cimg::toc();
} catch (CImgArgumentException& e) {
std::cerr << "tic/toc imbalance: " << e.what() << "\n";
// reset instrumentation or fall back to your own timer
} Prevention
- Always pair tic() with toc() on every code path, including early returns and catch blocks.
- Never place tic()/toc() inside tight loops or recursion; time the whole loop once instead.
- Use std::chrono or your own timer stack for deeply nested or multithreaded timing; tic/toc use shared static state.
- Add a debug assert that tic and toc call counts are equal at the end of each benchmarked section.
When it happens
Trigger: Calling cimg::tic() more times than the times buffer capacity (default 64) without intervening cimg::toc() calls — e.g. tic() inside deeply nested loops or recursive functions where every iteration/level pushes a new entry but toc() is never called, or unbalanced tic/toc pairs in instrumented code.
Common situations: Timing a recursive algorithm with tic() at every recursion level; putting tic() inside a loop body instead of before it; forgetting toc() on early-return/error paths so entries accumulate; long-running instrumented code with thousands of tic calls.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- cimg::toc(): No previous call to 'cimg::tic()' has been made
- [cimg_appname_math_parser] CImg<%s>::%s: Call stack overflow
- cimg::SDL3_attr(): %s
- cimg::mod(): Specified modulo value is 0.
- cimg::fopen(): Specified file path is (null).
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/10a71df13f87b616.
Report an issue: GitHub.