[llvm] r187042 - Don't leak when expanding response files.

Rafael Espindola rafael.espindola at gmail.com
Wed Jul 24 07:32:01 PDT 2013


Author: rafael
Date: Wed Jul 24 09:32:01 2013
New Revision: 187042

URL: http://llvm.org/viewvc/llvm-project?rev=187042&view=rev
Log:
Don't leak when expanding response files.

Before this patch we would strdup each argument. If one was a response file,
we would replace it with the response file contents, leaking the original
strdup result.

We now don't strdup the originals and let StringSaver free any memory it
allocated. This also saves a bit of malloc traffic when response files are
not used.

Leak found by the valgrind build bot.

Modified:
    llvm/trunk/lib/Support/CommandLine.cpp

Modified: llvm/trunk/lib/Support/CommandLine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CommandLine.cpp?rev=187042&r1=187041&r2=187042&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CommandLine.cpp (original)
+++ llvm/trunk/lib/Support/CommandLine.cpp Wed Jul 24 09:32:01 2013
@@ -563,8 +563,19 @@ bool cl::ExpandResponseFiles(StringSaver
 
 namespace {
   class StrDupSaver : public StringSaver {
+    std::vector<char*> Dups;
+  public:
+    ~StrDupSaver() {
+      for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end();
+           I != E; ++I) {
+        char *Dup = *I;
+        free(Dup);
+      }
+    }
     const char *SaveString(const char *Str) LLVM_OVERRIDE {
-      return strdup(Str);
+      char *Dup = strdup(Str);
+      Dups.push_back(Dup);
+      return Dup;
     }
   };
 }
@@ -588,20 +599,14 @@ void cl::ParseEnvironmentOptions(const c
   // Get program's "name", which we wouldn't know without the caller
   // telling us.
   SmallVector<const char *, 20> newArgv;
-  newArgv.push_back(strdup(progName));
+  StrDupSaver Saver;
+  newArgv.push_back(Saver.SaveString(progName));
 
   // Parse the value of the environment variable into a "command line"
   // and hand it off to ParseCommandLineOptions().
-  StrDupSaver Saver;
   TokenizeGNUCommandLine(envValue, Saver, newArgv);
   int newArgc = static_cast<int>(newArgv.size());
   ParseCommandLineOptions(newArgc, &newArgv[0], Overview);
-
-  // Free all the strdup()ed strings.
-  for (SmallVectorImpl<const char *>::iterator i = newArgv.begin(),
-                                               e = newArgv.end();
-       i != e; ++i)
-    free(const_cast<char *>(*i));
 }
 
 void cl::ParseCommandLineOptions(int argc, const char * const *argv,
@@ -618,7 +623,7 @@ void cl::ParseCommandLineOptions(int arg
   // Expand response files.
   SmallVector<const char *, 20> newArgv;
   for (int i = 0; i != argc; ++i)
-    newArgv.push_back(strdup(argv[i]));
+    newArgv.push_back(argv[i]);
   StrDupSaver Saver;
   ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv);
   argv = &newArgv[0];
@@ -914,13 +919,6 @@ void cl::ParseCommandLineOptions(int arg
   PositionalOpts.clear();
   MoreHelp->clear();
 
-  // Free the memory allocated by ExpandResponseFiles.
-  // Free all the strdup()ed strings.
-  for (SmallVectorImpl<const char *>::iterator i = newArgv.begin(),
-                                               e = newArgv.end();
-       i != e; ++i)
-    free(const_cast<char *>(*i));
-
   // If we had an error processing our arguments, don't let the program execute
   if (ErrorParsing) exit(1);
 }





More information about the llvm-commits mailing list