{"record":{"id":"10a71df13f87b616","repo":"Yalantis/uCrop","slug":"cimg-tic-too-much-calls-to-cimg-tic-witho","errorCode":null,"errorMessage":"cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'.","messagePattern":"cimg::tic\\(\\): Too much calls to 'cimg::tic\\(\\)' without calls to 'cimg::toc\\(\\)'\\.","errorType":"exception","errorClass":"CImgArgumentException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":70189,"sourceCode":"          cimg_snprintf(command,command._width,\"%s.gz\",filename_local);\n          std::rename(command,filename_local);\n        }\n      }\n\n      return filename_local;\n    }\n\n    // Implement a tic/toc mechanism to display elapsed time of algorithms.\n    inline cimg_uint64 tictoc(const bool is_tic) {\n      cimg::mutex(2);\n      static CImg<cimg_uint64> times(64);\n      static unsigned int pos = 0;\n      const cimg_uint64 t1 = cimg::time();\n      if (is_tic) {\n        // Tic.\n        times[pos++] = t1;\n        if (pos>=times._width)\n          throw CImgArgumentException(\"cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'.\");\n        cimg::mutex(2,0);\n        return t1;\n      }\n\n      // Toc.\n      if (!pos)\n        throw CImgArgumentException(\"cimg::toc(): No previous call to 'cimg::tic()' has been made.\");\n      const cimg_uint64\n        t0 = times[--pos],\n        dt = t1>=t0?(t1 - t0):cimg::type<cimg_uint64>::max();\n      const unsigned int\n        edays = (unsigned int)(dt/86400000.),\n        ehours = (unsigned int)((dt - edays*86400000.)/3600000.),\n        emin = (unsigned int)((dt - edays*86400000. - ehours*3600000.)/60000.),\n        esec = (unsigned int)((dt - edays*86400000. - ehours*3600000. - emin*60000.)/1000.),\n        ems = (unsigned int)(dt - edays*86400000. - ehours*3600000. - emin*60000. - esec*1000.);\n      if (!edays && !ehours && !emin && !esec)\n        std::fprintf(cimg::output(),\"%s[CImg]%*sElapsed time: %u ms%s\\n\",","sourceCodeStart":70171,"sourceCodeEnd":70207,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L70171-L70207","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncimg_forXY(img,x,y) {\n  cimg::tic(); // pushes a new entry every iteration -> overflow after 64 iterations\n  process(img(x,y));\n  cimg::toc();\n}\n// after\ncimg::tic();            // time the whole loop once\ncimg_forXY(img,x,y) process(img(x,y));\ncimg::toc();","handlingStrategy":"validation","validationCode":"// Keep a running balance of tic/toc and assert it stays within capacity (default stack = 64)\nstatic int ticDepth = 0;\n#define SAFE_TIC() do { if (ticDepth >= 64) { fprintf(stderr,\"tic overflow\\n\"); } else { cimg::tic(); ++ticDepth; } } while(0)\n#define SAFE_TOC() do { if (ticDepth > 0) { cimg::toc(); --ticDepth; } } while(0)","typeGuard":null,"tryCatchPattern":"try {\n  cimg::tic();\n  measure();\n  cimg::toc();\n} catch (CImgArgumentException& e) {\n  std::cerr << \"tic/toc imbalance: \" << e.what() << \"\\n\";\n  // reset instrumentation or fall back to your own timer\n}","preventionTips":["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."],"tags":["timing","profiling","tic-toc","stack-overflow","cimg"],"backgroundTag":"internal-invariant-violation","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}