{"record":{"id":"be30435dc49fa22b","repo":"Yalantis/uCrop","slug":"cimg-toc-no-previous-call-to-cimg-tic-has","errorCode":null,"errorMessage":"cimg::toc(): No previous call to 'cimg::tic()' has been made.","messagePattern":"cimg::toc\\(\\): No previous call to 'cimg::tic\\(\\)' has been made\\.","errorType":"exception","errorClass":"CImgArgumentException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":70196,"sourceCode":"\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\",\n                     cimg::t_red,1 + 2*pos,\"\",ems,cimg::t_normal);\n      else {\n        if (!edays && !ehours && !emin)\n          std::fprintf(cimg::output(),\"%s[CImg]%*sElapsed time: %u sec %u ms%s\\n\",\n                       cimg::t_red,1 + 2*pos,\"\",esec,ems,cimg::t_normal);\n        else {\n          if (!edays && !ehours)","sourceCodeStart":70178,"sourceCodeEnd":70214,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L70178-L70214","documentation":"cimg::toc() reads the most recent timestamp pushed by cimg::tic() from an internal stack to compute the elapsed time. If the stack position counter is 0 — i.e. tic() was never called, or toc() has already been called for every tic() — there is nothing to pop, so CImg throws CImgArgumentException instead of reading garbage data.","triggerScenarios":"Calling cimg::toc() before any cimg::tic(), calling toc() more times than tic(), or calling toc() after an earlier unbalanced sequence already consumed the stack (e.g. toc() invoked from a different thread or after an exception path skipped the tic()).","commonSituations":"Copy-pasted toc() leftover from removed tic() instrumentation; calling toc() in a destructor/error handler while tic() was only called on the happy path; mixing tic/toc across threads (the stack is per-process static state); mismatched tic/toc counts in instrumented libraries.","solutions":["Verify each toc() is preceded by exactly one tic() on the same execution path; log or assert the tic/toc pairing during development.","Remove or guard stray toc() calls (e.g. in destructors or catch blocks) so they only run when a tic() actually happened.","Do not share tic()/toc() across threads; use per-thread timers (e.g. std::chrono::steady_clock) if measurement happens concurrently.","If the tic() may be skipped conditionally, skip the matching toc() with the same condition so counts stay balanced."],"exampleFix":"// before\nvoid run(bool skip) {\n  if (!skip) cimg::tic();\n  do_work();\n  cimg::toc(); // throws when skip==true because tic() was never called\n}\n// after\nvoid run(bool skip) {\n  if (!skip) cimg::tic();\n  do_work();\n  if (!skip) cimg::toc(); // balanced with tic()\n}","handlingStrategy":"validation","validationCode":"// Track whether a tic() is outstanding before calling toc()\nstatic bool ticActive = false;\n#define SAFE_TIC() do { cimg::tic(); ticActive = true; } while(0)\n#define SAFE_TOC() do { if (!ticActive) { fprintf(stderr,\"toc without tic\\n\"); } else { cimg::toc(); ticActive = false; } } while(0)","typeGuard":null,"tryCatchPattern":"try {\n  cimg::toc();\n} catch (CImgArgumentException& e) {\n  std::cerr << \"toc() without tic(): \" << e.what() << \"\\n\";\n  // recover: re-instrument or ignore the stray timing call\n}","preventionTips":["Guard stray toc() calls in destructors/error handlers so they only run if tic() actually happened.","Keep tic/toc pairs in the same function/scope so matching is obvious.","Never share tic()/toc() across threads; the stack is static shared state.","Count tic/toc invocations in debug builds and assert equality at shutdown."],"tags":["timing","profiling","tic-toc","invalid-state","cimg"],"backgroundTag":"invalid-state-transition","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"}