Avoid building constant strings on the stack
authorDavin McCall <davmac@davmac.org>
Mon, 23 Dec 2019 01:03:12 +0000 (11:03 +1000)
committerDavin McCall <davmac@davmac.org>
Mon, 23 Dec 2019 01:03:12 +0000 (11:03 +1000)
In a few places cts::literal was used locally within a function,
resulting in the (constexpr) result string object being allocated on the
stack. Move these to namespace scope.

src/dinit.cc
src/includes/static-string.h

index 4550ddcb269b2a5c4795ec2549af6c664421e35a..a5a7cd49a9b5f630cd90640af93cd4c82016f0ca 100644 (file)
@@ -172,6 +172,10 @@ namespace {
     control_socket_watcher control_socket_io;
     console_input_watcher console_input_io;
     log_flush_timer_t log_flush_timer;
+
+    // These need to be at namespace scope to prevent causing stack allocations when using them:
+    constexpr auto shutdown_exec = literal(SBINDIR) + "/" + "shutdown";
+    constexpr auto error_exec_sd = literal("Error executing ") + shutdown_exec + ": ";
 }
 
 // Main entry point
@@ -494,10 +498,8 @@ int dinit_main(int argc, char **argv)
         }
         
         // Fork and execute dinit-reboot.
-        constexpr auto shutdown_exec = literal(SBINDIR) + "/shutdown";
         execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", cmd_arg, nullptr);
-        log(loglevel_t::ERROR, (literal("Could not execute ") + SBINDIR + "/shutdown: ").c_str(),
-                strerror(errno));
+        log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
         
         // PID 1 must not actually exit, although we should never reach this point:
         while (true) {
@@ -847,9 +849,8 @@ static void sigquit_cb(eventloop_t &eloop) noexcept
 {
     // This performs an immediate shutdown, without service rollback.
     close_control_socket();
-    constexpr auto shutdown_exec = literal(SBINDIR) + "/shutdown";
     execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", (char *) 0);
-    log(loglevel_t::ERROR, literal("Error executing ") + SBINDIR + "/sbin/shutdown: ", strerror(errno));
+    log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
     sync(); // since a hard poweroff might be required at this point...
 }
 
index 3d42f2e10a63e330e9c1df3bcf3b9ca96b36e8f0..9cc6042832fa6e743b3f330fc8309f73bb2ceaa3 100644 (file)
 // string, or simply assign or cast to a 'const char *':
 //
 //   const char * cstr = str3; // now points to "onetwo"
+//
+// Note that to be most effective, it is necessary to construct literals at file/namespace scope.
+// If they are constructed as locals, the compiler may reconstruct the object each time the
+// function is called (i.e. it will allocate stack and copy the constant string result into it).
 
 namespace cts {