diff --git a/lib/checkother.cpp b/lib/checkother.cpp
index 7a6682973ff7..7e9e95d20962 100644
--- a/lib/checkother.cpp
+++ b/lib/checkother.cpp
@@ -4364,7 +4364,8 @@ void CheckOther::overlappingWriteUnion(const Token *tok)
 
 void CheckOther::overlappingWriteFunction(const Token *tok)
 {
-    const std::string &funcname = tok ? tok->str() : emptyString;
+    static const std::string s_empty_string;
+    const std::string &funcname = tok ? tok->str() : s_empty_string;
     reportError(tok, Severity::error, "overlappingWriteFunction", "Overlapping read/write in " + funcname + "() is undefined behavior");
 }
 
diff --git a/lib/library.cpp b/lib/library.cpp
index 6872553c791d..a41f527dba9d 100644
--- a/lib/library.cpp
+++ b/lib/library.cpp
@@ -143,6 +143,8 @@ struct Library::LibraryData
     std::unordered_set<std::string> mEntrypoints;
 };
 
+const std::string Library::mEmptyString;
+
 Library::Library()
     : mData(new LibraryData())
 {}
@@ -1588,9 +1590,9 @@ Library::UseRetValType Library::getUseRetValType(const Token *ftok) const
 const std::string& Library::returnValue(const Token *ftok) const
 {
     if (isNotLibraryFunction(ftok))
-        return emptyString;
+        return mEmptyString;
     const auto it = utils::as_const(mData->mReturnValue).find(getFunctionName(ftok));
-    return it != mData->mReturnValue.cend() ? it->second : emptyString;
+    return it != mData->mReturnValue.cend() ? it->second : mEmptyString;
 }
 
 const std::string& Library::returnValueType(const Token *ftok) const
@@ -1601,10 +1603,10 @@ const std::string& Library::returnValueType(const Token *ftok) const
             if (contTok->valueType() && contTok->valueType()->container)
                 return contTok->valueType()->container->getReturnType(ftok->str());
         }
-        return emptyString;
+        return mEmptyString;
     }
     const auto it = utils::as_const(mData->mReturnValueType).find(getFunctionName(ftok));
-    return it != mData->mReturnValueType.cend() ? it->second : emptyString;
+    return it != mData->mReturnValueType.cend() ? it->second : mEmptyString;
 }
 
 int Library::returnValueContainer(const Token *ftok) const
@@ -1794,7 +1796,7 @@ const std::string& Library::blockstart(const std::string &file) const
     if (map_it != mData->mExecutableBlocks.end()) {
         return map_it->second.start();
     }
-    return emptyString;
+    return mEmptyString;
 }
 
 const std::string& Library::blockend(const std::string &file) const
@@ -1805,7 +1807,7 @@ const std::string& Library::blockend(const std::string &file) const
     if (map_it != mData->mExecutableBlocks.end()) {
         return map_it->second.end();
     }
-    return emptyString;
+    return mEmptyString;
 }
 
 bool Library::iskeyword(const std::string &file, const std::string &keyword) const
diff --git a/lib/library.h b/lib/library.h
index 6f51e6842523..ae65891b97aa 100644
--- a/lib/library.h
+++ b/lib/library.h
@@ -52,6 +52,8 @@ namespace tinyxml2 {
 class CPPCHECKLIB Library {
     friend struct LibraryHelper; // for testing
 
+    static const std::string mEmptyString;
+
 public:
     Library();
     ~Library();
@@ -252,7 +254,7 @@ class CPPCHECKLIB Library {
 
         const std::string& getReturnType(const std::string& function) const {
             const auto i = utils::as_const(functions).find(function);
-            return (i != functions.end()) ? i->second.returnType : emptyString;
+            return (i != functions.end()) ? i->second.returnType : mEmptyString;
         }
 
         static Yield yieldFrom(const std::string& yieldName);
@@ -348,7 +350,7 @@ class CPPCHECKLIB Library {
 
     const std::string& validarg(const Token *ftok, int argnr) const {
         const ArgumentChecks *arg = getarg(ftok, argnr);
-        return arg ? arg->valid : emptyString;
+        return arg ? arg->valid : mEmptyString;
     }
 
     const ArgumentChecks::IteratorInfo *getArgIteratorInfo(const Token *ftok, int argnr) const {
diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp
index fc3a82a502b2..fe76b5e0cfdf 100644
--- a/lib/symboldatabase.cpp
+++ b/lib/symboldatabase.cpp
@@ -3585,8 +3585,10 @@ std::string Type::name() const
         start = start->tokAt(1);
     else if (start->str() == "class")
         start = start->tokAt(1);
-    else if (!start->isName())
-        return emptyString;
+    else if (!start->isName()) {
+        static const std::string s_empty_string;
+        return s_empty_string;
+    }
     const Token* next = start;
     while (Token::Match(next, "::|<|>|(|)|[|]|*|&|&&|%name%")) {
         if (Token::Match(next, "<|(|[") && next->link())
diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h
index 67b7c6750984..24ae777c52fb 100644
--- a/lib/symboldatabase.h
+++ b/lib/symboldatabase.h
@@ -125,7 +125,8 @@ class CPPCHECKLIB Type {
     std::string name() const;
 
     const std::string& type() const {
-        return classDef ? classDef->str() : emptyString;
+        static const std::string s_empty_string;
+        return classDef ? classDef->str() : s_empty_string;
     }
 
     bool isClassType() const;
@@ -294,7 +295,8 @@ class CPPCHECKLIB Variable {
         if (mNameToken)
             return mNameToken->str();
 
-        return emptyString;
+        static const std::string s_empty_string;
+        return s_empty_string;
     }
 
     /**
diff --git a/lib/token.cpp b/lib/token.cpp
index 55ac12ad9ce4..aea4c3a713f0 100644
--- a/lib/token.cpp
+++ b/lib/token.cpp
@@ -56,6 +56,7 @@ namespace {
 }
 
 const std::list<ValueFlow::Value> TokenImpl::mEmptyValueList;
+const std::string Token::mEmptyString;
 
 Token::Token(TokensFrontBack &tokensFrontBack)
     : mTokensFrontBack(tokensFrontBack)
diff --git a/lib/token.h b/lib/token.h
index eb2434d1a844..21a2c4ce6af3 100644
--- a/lib/token.h
+++ b/lib/token.h
@@ -167,6 +167,8 @@ class CPPCHECKLIB Token {
 private:
     TokensFrontBack& mTokensFrontBack;
 
+    static const std::string mEmptyString;
+
 public:
     Token(const Token &) = delete;
     Token& operator=(const Token &) = delete;
@@ -256,7 +258,7 @@ class CPPCHECKLIB Token {
     const std::string &strAt(int index) const
     {
         const Token *tok = this->tokAt(index);
-        return tok ? tok->mStr : emptyString;
+        return tok ? tok->mStr : mEmptyString;
     }
 
     /**
@@ -1265,7 +1267,7 @@ class CPPCHECKLIB Token {
      * @return the original name.
      */
     const std::string & originalName() const {
-        return mImpl->mOriginalName ? *mImpl->mOriginalName : emptyString;
+        return mImpl->mOriginalName ? *mImpl->mOriginalName : mEmptyString;
     }
 
     const std::list<ValueFlow::Value>& values() const {
diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp
index a5d46383a2d2..496646632825 100644
--- a/lib/tokenlist.cpp
+++ b/lib/tokenlist.cpp
@@ -77,7 +77,8 @@ TokenList::~TokenList()
 const std::string& TokenList::getSourceFilePath() const
 {
     if (getFiles().empty()) {
-        return emptyString;
+        static const std::string s_empty_string;
+        return s_empty_string;
     }
     return getFiles()[0];
 }
diff --git a/lib/vf_analyzers.cpp b/lib/vf_analyzers.cpp
index 5f850f5d6d57..9b5a4d838cdb 100644
--- a/lib/vf_analyzers.cpp
+++ b/lib/vf_analyzers.cpp
@@ -435,7 +435,8 @@ struct ValueFlowAnalyzer : Analyzer {
             {"^=", "^="}};
         auto it = lookup.find(assign);
         if (it == lookup.end()) {
-            return emptyString;
+            static const std::string s_empty_string;
+            return s_empty_string;
         }
         return it->second;
     }