| Summary: | memory leak in putenv | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Abdul Khan <khana> |
| Component: | bin | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 1.0-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
Responsible Changed From-To: gnats-admin->freebsd-bugs Misfiled. Futhermore, see PR 18515 State Changed From-To: open->closed Due to bad API design, putenv(3) is a memory leaker. It's even documented in the man-page. |
sorry about the last one.. i was a little too quick on the draw :) this one should work: #include <iostream.h> #include <stdlib.h> extern char** environ; class Exception { public: virtual char* getErrorMessage() = 0; }; class NullPointerException : public Exception { public: virtual char* getErrorMessage() { return "Null Pointer Exception"; }; }; class EnvironmentVariable { public: EnvironmentVariable(char* variable_name) { if (!variable_name) throw NullPointerException(); else name = strdup(variable_name); setEnvironmentVariableOneTime=false; }; void setEnv(char* value) { int i = 0, j = 0; while (environ[i]) { while (name[j] && environ[i][j] && name[j] == environ[i][j]) j++; if (environ[i][j] == '=' && !name[j]) { if (setEnvironmentVariableOneTime) { environ[i] = (char*) realloc (environ[i], sizeof(char)* (strlen (value) + strlen (name) + 1 + 1)); sprintf(environ[i], "%s=%s", name, value); } else { int k = i; while (environ[k]) k++; char** new_environ = (char**) malloc(sizeof(char*)*(k+1)); for(int n=0;n<k;n++) { new_environ[n] = (char*) malloc(sizeof(char)*(strlen(environ[n])+1)); strcpy(new_environ[n], environ[n]); } new_environ[n]=NULL; new_environ[i] = (char*) realloc (new_environ[i], sizeof(char)* (strlen (value) + strlen (name) + 1 + 1)); sprintf(new_environ[i], "%s=%s", name, value); clearenv(); environ=new_environ; } break; } i++; } if (!environ[i]) { char* new_env = (char*) malloc(sizeof(char)* (strlen (value) + strlen (name) + 1 + 1)); sprintf(new_env, "%s=%s", name, value); putenv(new_env); } else { setEnvironmentVariableOneTime = true; } } void setEnvWithLeak(char* value) { char* env = (char *) malloc (sizeof(char)* (strlen (value) + strlen (name) + 1 + 1)); sprintf(env, "%s=%s", name, value); putenv(env); } char* getEnv() {return getenv(name);}; virtual ~EnvironmentVariable() { free(name);}; private: char* name; static bool setEnvironmentVariableOneTime; }; int main(int argc, char** argv) { char * str = 0; try { if (argc < 4) { cout << "Usage: env_mem_leak <environment variable name> "; cout << "<iterations> <bifurcations>" << endl; cout << "Where iterations is the number of times to set the variable "; cout << "and bifrucations is the number of changes in the length of "; cout << "the string that is put into the environment variable" << endl; } EnvironmentVariable myenv(argv[1]); int iterations = atoi(argv[2]); int bifurcations = atoi(argv[3]); str = (char*) malloc(sizeof(char)*(bifurcations+1)); for (int i=0; i < iterations; i++) { memset(str, 'A', i % bifurcations); str[(i % bifurcations) + 1]='\0'; myenv.setEnv(str); ////switch these to see the memory leak problem in purify!!!!!!!!!! //myenv.setEnvWithLeak(str); cout << myenv.getEnv() << endl; } } catch(Exception& e) { cout << endl << e.getErrorMessage() << endl; }; if (str) free(str); return 0; }