diff --git a/src/json_workload.cpp b/src/json_workload.cpp
index 0bc0a9ba2e1a3a436a9536727a9bb149c7679413..3fac657f74dfd8bb95df39fd7602963cd82cd35b 100644
--- a/src/json_workload.cpp
+++ b/src/json_workload.cpp
@@ -32,6 +32,16 @@ Session::Session(
     jobs = list<const Job *>();
 }
 
+Session::~Session()
+{
+    for (const Job *job : jobs){
+        delete job;
+    }
+    jobs.clear();
+    preceding_sessions.clear();
+    following_sessions.clear();
+}
+
 Workload::~Workload()
 {
     deallocate();
@@ -174,6 +184,7 @@ Job *Workload::job_from_json_object(const Value &object)
     return j;
 }
 
+
 bool JobComparator::operator()(const Job *j1, const Job *j2) const
 {
     PPK_ASSERT_ERROR(j1->id.find('!') != string::npos,
@@ -187,7 +198,11 @@ bool JobComparator::operator()(const Job *j1, const Job *j2) const
     if (id1.length() == id2.length()) /* same length: lexicographic order */
         return id1 < id2;
     return id1.length() < id2.length();
+}
 
+bool JobComparator::operator()(Job j1, Job j2) const
+{
+    return JobComparator::operator()(&j1, &j2);
 }
 
 bool SessionComparator::operator()(const Session *s1, const Session *s2) const
@@ -423,7 +438,7 @@ Job *Parser::job_from_json_object(string user_name, const Value &object)
     return j;
 }
 
-string Parser::json_description_string_from_job(Job *job)
+string Parser::json_description_string_from_job(const Job *job)
 {
     PPK_ASSERT_ERROR(job->id != "", "A job must have the field 'id'.");
     PPK_ASSERT_ERROR(
diff --git a/src/json_workload.hpp b/src/json_workload.hpp
index 4e587b152ee76e83a9fd89cd0fcba8703e91776c..d7e8fca93ade62be7336dd6f358338490f6987ad 100644
--- a/src/json_workload.hpp
+++ b/src/json_workload.hpp
@@ -13,7 +13,7 @@
 #include <utility>
 
 struct JobAlloc;
-struct Session;
+class Session;
 
 #define DATE_NEVER -1.0
 #define DATE_UNKNOWN -2.0
@@ -53,6 +53,7 @@ struct JobAlloc
 struct JobComparator
 {
     bool operator()(const Job *j1, const Job *j2) const;
+    bool operator()(Job j1, Job j2) const;
 };
 
 struct Profile
@@ -62,8 +63,12 @@ struct Profile
     std::string description;
 };
 
-struct Session
+class Session
 {
+public:
+    Session(unsigned int id, double first_submit_time, unsigned int nb_jobs);
+    ~Session();
+
     unsigned int id;
     double
         original_first_submit_time; /* the submit time of the first job in this
@@ -76,7 +81,6 @@ struct Session
     std::map<Session *, double> preceding_sessions; /* pair (Session, t_time) */
     std::set<Session *> following_sessions;
 
-    Session(unsigned int id, double first_submit_time, unsigned int nb_jobs);
 };
 
 struct SessionComparator
@@ -126,7 +130,7 @@ struct Parser
     static Job *job_from_json_object(
         const std::string user_name, const rapidjson::Value &object);
     // with format 'user-name!jobID'
-    static std::string json_description_string_from_job(Job *job);
+    static std::string json_description_string_from_job(const Job *job);
     static Session *session_from_json_object(const std::string user_name,
         const rapidjson::Value &object, std::list<unsigned int> *prec_sessions,
         std::list<double> *tt_after_prec_sessions);
diff --git a/src/scheds/HARD_DEFINED_VAR.hpp b/src/scheds/HARD_DEFINED_VAR.hpp
index f8115b5c77374bf6c7fc5c7bbdd3ccae6e5227b7..eac0f44b8a4d9a1cc6a85ccddc22743b855ef88a 100644
--- a/src/scheds/HARD_DEFINED_VAR.hpp
+++ b/src/scheds/HARD_DEFINED_VAR.hpp
@@ -2,4 +2,6 @@
 #define NB_CORE_PER_MACHINE 16
 #define INITIAL_MACHINE_STATE AWAKE
 #define PSTATE_AWAKE 0 
-#define PSTATE_ASLEEP 1
\ No newline at end of file
+#define PSTATE_ASLEEP 1
+
+#define EPSILON 0.00001 /* For float rounding issues */
\ No newline at end of file
diff --git a/src/scheds/bin_packing.cpp b/src/scheds/bin_packing.cpp
index dc11ac6feb0f3edd268a05c525d5e525aacb3a13..bd8bb146be70ad39830075cd9c1f4a4f7bbb5767 100644
--- a/src/scheds/bin_packing.cpp
+++ b/src/scheds/bin_packing.cpp
@@ -37,6 +37,9 @@ BinPacking::BinPacking(Workload *workload, SchedulingDecision *decision,
 
 BinPacking::~BinPacking()
 {
+    for (auto host : listofHosts)
+        delete host;
+    listofHosts.clear();
 }
 
 std::string BinPacking::hosts_to_string(std::list<SortableHost *> listofHosts)
diff --git a/src/scheds/bin_packing_energy.cpp b/src/scheds/bin_packing_energy.cpp
index 9617841d2be773878a8ff9ee984db0351497d7b7..e98405c279a8e936b558865be5a0c1eefe436f89 100644
--- a/src/scheds/bin_packing_energy.cpp
+++ b/src/scheds/bin_packing_energy.cpp
@@ -65,6 +65,9 @@ BinPackingEnergy::BinPackingEnergy(Workload *workload,
 
 BinPackingEnergy::~BinPackingEnergy()
 {
+    for (auto host : listofHosts)
+        delete host;
+    listofHosts.clear();
 }
 
 std::string BinPackingEnergy::machine_state_to_string(
diff --git a/src/users/broker.cpp b/src/users/broker.cpp
index 0430cc926412a562bde3d9f5b1f7de1849560575..f325bfa90be79a06f64e610a8d4f5917239cde0a 100644
--- a/src/users/broker.cpp
+++ b/src/users/broker.cpp
@@ -8,6 +8,7 @@
 #include "../pempek_assert.hpp"
 #include "rapidjson/rapidjson.h"
 #include <loguru.hpp>
+#include <memory>
 using namespace rapidjson;
 
 Broker::Broker(rapidjson::Document *user_description_file)
@@ -15,6 +16,16 @@ Broker::Broker(rapidjson::Document *user_description_file)
     /* Parse description file and call constructor for each user */
     if (!user_description_file->ObjectEmpty())
     {
+        if (user_description_file->HasMember("core_limit_per_user"))
+        {
+            PPK_ASSERT_ERROR(
+                (*user_description_file)["core_limit_per_user"].IsInt(),
+                "Invalid user_description file: field "
+                "'core_limit_per_user' should be an int.");
+            core_limit_per_user
+                = (*user_description_file)["core_limit_per_user"].GetInt();
+            // otherwise, initialized at std::numeric_limits<int>::max()
+        }
         if (user_description_file->HasMember("dm_window"))
         {
             const Value &dm_param = (*user_description_file)["dm_window"];
@@ -143,8 +154,7 @@ Broker::~Broker()
     {
         delete it.second;
     }
-    for (auto itr = dynamic_jobs.begin(); itr != dynamic_jobs.end(); itr++)
-        delete itr->second;
+
     dynamic_jobs.clear();
     users_to_wake.clear();
 }
@@ -155,10 +165,10 @@ double Broker::next_submission(double date) const
 }
 
 void Broker::jobs_to_submit(
-    double date, list<Job *> &jobs, list<Profile *> &profiles)
+    double date, list<Job> &jobs, list<const Profile *> &profiles)
 {
-    jobs = list<Job *>();
-    profiles = list<Profile *>();
+    jobs = list<Job>();
+    profiles = list<const Profile *>();
 
     User *user = user_queue.front();
     double planned_date_submission = user->next_submission();
@@ -171,15 +181,25 @@ void Broker::jobs_to_submit(
     while (planned_date_submission == user->next_submission())
     {
         user_queue.pop_front();
-        list<Job *> user_jobs;
-        list<Profile *> user_profiles;
+        unsigned int nb_core_requested = 0;
+        list<shared_ptr<Job>> user_jobs;
+        list<const Profile *> user_profiles;
         user->jobs_to_submit(date, user_jobs, user_profiles);
 
-        for (Job *job : user_jobs)
+        for (shared_ptr<Job> job : user_jobs)
         {
-            jobs.push_back(job);
-            dynamic_jobs[job->id] = job;
-            job->status = WAITING;
+            nb_core_requested = nb_core_requested + job->nb_requested_resources;
+
+            if (nb_core_requested > core_limit_per_user)
+            {
+                job->status = KILLED;
+            }
+            else
+            {
+                jobs.push_back(*job);
+                dynamic_jobs[job->id] = job;
+                job->status = WAITING;
+            }
         }
         profiles.splice(profiles.end(), user_profiles);
 
@@ -231,7 +251,7 @@ void Broker::update_status_if_dyn_job(
     {
         string user_name = job_id.substr(0, job_id.find('!'));
         User *user = users[user_name];
-        Job *current_job = it->second;
+        shared_ptr<Job> current_job = it->second;
 
         switch (status)
         {
@@ -250,7 +270,7 @@ void Broker::update_status_if_dyn_job(
 
             /* Add potentially interested user to the map of users to wake up */
             if (users_to_wake.find(user) == users_to_wake.end())
-                users_to_wake.emplace(user, list<Job *>());
+                users_to_wake.emplace(user, list<shared_ptr<Job>>());
 
             /* ..and keep track of its recently ended jobs */
             users_to_wake[user].push_back(current_job);
@@ -265,7 +285,7 @@ void Broker::update_status_if_dyn_job(
 
             /* Add potentially interested user to the map of users to wake up */
             if (users_to_wake.find(user) == users_to_wake.end())
-                users_to_wake.emplace(user, list<Job *>());
+                users_to_wake.emplace(user, list<shared_ptr<Job>>());
 
             /* ..and keep track of its recently ended jobs */
             users_to_wake[user].push_back(current_job);
diff --git a/src/users/broker.hpp b/src/users/broker.hpp
index 88d4de90d80eddeeb862064cfea39554db80ca68..cbb389debad61982e76d7df8082a14d30b594ef8 100644
--- a/src/users/broker.hpp
+++ b/src/users/broker.hpp
@@ -34,7 +34,7 @@ public:
      * @param[out] profiles The list of profiles used by the jobs, if new.
      */
     void jobs_to_submit(
-        double date, list<Job *> &jobs, list<Profile *> &profiles);
+        double date, list<Job> &jobs, list<const Profile *> &profiles);
 
     /**
      * @brief Ackowledge the latest execution-related activity and forward the
@@ -48,10 +48,11 @@ public:
 
 private:
     map<string, User *> users;
+    unsigned int core_limit_per_user = std::numeric_limits<int>::max();
     list<User *> user_queue;
-    map<string, Job *> dynamic_jobs = map<string, Job *>();
-    map<User *, list<Job *>> users_to_wake
-        = map<User *, list<Job *>>();
+    map<string, shared_ptr<Job>> dynamic_jobs = map<string, shared_ptr<Job>>();
+    map<User *, list<shared_ptr<Job>>> users_to_wake
+        = map<User *, list<shared_ptr<Job>>>();
 
 private:
     /* Deterministic generation of seeds for users that use randomness */
diff --git a/src/users/dynscheduler.cpp b/src/users/dynscheduler.cpp
index 2e2f3e01ee93c34aa437e5f0701751f33c3b0d1d..8ff436c4d834a786ef2c0fe8ed086737f6954f40 100644
--- a/src/users/dynscheduler.cpp
+++ b/src/users/dynscheduler.cpp
@@ -41,16 +41,6 @@ void DynScheduler::on_simulation_start(
         /* Check for optional parameters */
         if (!_variant_options->ObjectEmpty())
         {
-            if (_variant_options->HasMember("core_limit_per_user"))
-            {
-                PPK_ASSERT_ERROR(
-                    (*_variant_options)["core_limit_per_user"].IsInt(),
-                    "Invalid user_description file: field "
-                    "'core_limit_per_user' should be an int.");
-                core_limit_per_user
-                    = (*_variant_options)["core_limit_per_user"].GetInt();
-                // otherwise, initialized at std::numeric_limits<int>::max()
-            }
             if (_variant_options->HasMember("log_user_stats")
                 && (*_variant_options)["log_user_stats"].GetBool())
             {
@@ -148,53 +138,46 @@ void DynScheduler::end_broker(double date)
 
 void DynScheduler::submit_broker_jobs(double date)
 {
-    std::list<Job *> jobs;
-    std::list<Profile *> profiles;
+    std::list<Job> jobs;
+    std::list<const Profile *> profiles;
     broker->jobs_to_submit(date, jobs, profiles);
 
-    if (!profiles.empty())
+    if (!profiles.empty()) {
         dyn_register_profiles(profiles, date);
+
+        /* Profiles won't be used anymore, free memory */
+        for (const Profile *profile : profiles){
+            delete profile;
+        }
+    }
     dyn_submit(jobs, date);
 }
 
-void DynScheduler::dyn_submit(std::list<Job *> jobs, double date)
+void DynScheduler::dyn_submit(std::list<Job> jobs, double date)
 {
-    std::map<std::string, int> core_per_user;
-
-    for (Job *current_job : jobs)
+    for (Job current_job : jobs)
     {
-        std::string fullID = current_job->id;
+        std::string fullID = current_job.id;
         PPK_ASSERT_ERROR(fullID.find('!') != std::string::npos,
-            "Dynamicaly submitted jobs should have the format "
+            "Dynamically submitted jobs should have the format "
             "'user_name!jobID'.");
         std::string user_name = fullID.substr(0, fullID.find('!'));
         fullID.erase(0, fullID.find('!') + 1);
         std::string jobID = fullID;
+        std::string job_description
+            = Parser::json_description_string_from_job(&current_job);
+        std::string empty_profile_description
+            = std::string(); // has already been sent
 
-        // REFAC: move to broker
-        core_per_user[user_name]
-            = core_per_user[user_name] + current_job->nb_requested_resources;
+        /* Register the job to batsim */
+        _decision->add_submit_job(user_name, jobID, current_job.profile,
+            job_description, empty_profile_description, date, true);
 
-        if (core_per_user[user_name] > core_limit_per_user)
-        {
-            current_job->status = KILLED;
-        }
-        else
-        {
-            std::string job_description
-                = Parser::json_description_string_from_job(current_job);
-            std::string empty_profile_description
-                = std::string(); // has already been sent
-
-            /* Register the job to batsim */
-            _decision->add_submit_job(user_name, jobID, current_job->profile,
-                job_description, empty_profile_description, date, true);
-        }
     }
 }
 
 void DynScheduler::dyn_register_profiles(
-    std::list<Profile *> profiles, double date)
+    std::list<const Profile *> profiles, double date)
 {
     for (auto profile : profiles)
     {
diff --git a/src/users/dynscheduler.hpp b/src/users/dynscheduler.hpp
index 677282a80c3c1cb82cc04f16660e02b5d1bda34c..602f72e376d6bae164d6066c539f7c05fe7f4db8 100644
--- a/src/users/dynscheduler.hpp
+++ b/src/users/dynscheduler.hpp
@@ -53,12 +53,12 @@ protected:
     /**
      * Dynamically registers to batsim the job `jobs` to submit.
      */
-    void dyn_submit(std::list<Job *> jobs, double date);
+    void dyn_submit(std::list<Job> jobs, double date);
 
     /**
      * Registers to batsim the profiles that will be used by the broker.
      */
-    void dyn_register_profiles(std::list<Profile *> profiles, double date);
+    void dyn_register_profiles(std::list<const Profile *> profiles, double date);
 
 protected:
     bool broker_enabled = false;
@@ -67,6 +67,5 @@ protected:
     bool next_submission_has_changed = false;
 
 private:
-    int core_limit_per_user = std::numeric_limits<int>::max();
     std::string log_folder = "";
 };
\ No newline at end of file
diff --git a/src/users/user.cpp b/src/users/user.cpp
index 6d38e6bc168b0283e26916a66990dc674493816b..495094dc1a7b98584ffb13eba0185d0e6e7b5947 100644
--- a/src/users/user.cpp
+++ b/src/users/user.cpp
@@ -21,7 +21,7 @@ int *User::get_dm_stat()
     return stat;
 }
 
-void User::wake_on_feedback(double date, std::list<Job *> &ended_jobs)
+void User::wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs)
 {
     return;
 }
diff --git a/src/users/user.hpp b/src/users/user.hpp
index d5feb399c5da551166ba392bde425cc39664ef27..7f7f151d450ca1496914eb7b93af5c663b207c16 100644
--- a/src/users/user.hpp
+++ b/src/users/user.hpp
@@ -4,9 +4,12 @@
 #include "rapidjson/document.h"
 #include <list>
 #include <string>
+#include <memory>
 
 #include "scheds/HARD_DEFINED_VAR.hpp"
 
+using namespace std;
+
 class User
 {
 public:
@@ -30,17 +33,17 @@ public:
      * @param[out] profiles The list of profiles used by the jobs, if new.
      */
     virtual void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+        double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles)
         = 0;
 
     /* For demand response users only: */
     virtual int *get_dm_stat();
 
     /* For users reacting to feedback: */
-    virtual void wake_on_feedback(double date, std::list<Job *> &ended_jobs);
+    virtual void wake_on_feedback(double date, list<shared_ptr<Job>> &ended_jobs);
 
 public:
-    std::string user_name;
+    string user_name;
 
 protected:
     double date_of_next_submission;
diff --git a/src/users/user_feedback.cpp b/src/users/user_feedback.cpp
index bdf922ea03d2459a11b7ad7d2d52598b33e645f2..515f62b5050a046dce1ae512f738f9d903bc4dc3 100644
--- a/src/users/user_feedback.cpp
+++ b/src/users/user_feedback.cpp
@@ -5,8 +5,6 @@
 #include <limits>
 #include <string>
 
-#define EPS 0.00001
-
 /* FeedbackUser */
 void FeedbackUser::init_FeedbackUser(
     std::string name, const rapidjson::Value &param)
@@ -82,13 +80,13 @@ void FeedbackUser::update_date_next_sub()
 }
 
 void FeedbackUser::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
-    jobs = std::list<Job *>();
-    profiles = std::list<Profile *>();
+    jobs = std::list<shared_ptr<Job>>();
+    profiles = std::list<const Profile *>();
 
     /* Add the free sessions starting now to the list of active sessions */
-    while (!free_sessions.empty() && free_sessions.top()->start_time < date + EPS)
+    while (!free_sessions.empty() && free_sessions.top()->start_time < date + EPSILON)
     {
         active_sessions.push_back(free_sessions.top());
         free_sessions.pop();
@@ -110,9 +108,9 @@ void FeedbackUser::jobs_to_submit(
         double offset = active_sess->start_time;
 
         while (!job_list->empty()
-            && job_list->front()->submission_time + offset < date + EPS)
+            && job_list->front()->submission_time + offset < date + EPSILON)
         {
-            Job *job = new Job(*job_list->front()); // Cast const Job * -> Job *
+            shared_ptr<Job> job = shared_ptr<Job>(new Job(*job_list->front())); // Cast const Job * -> shared_ptr<Job>
             Profile *job_profile = new Profile();
 
             /* Handle the job according to the user behavior. */
@@ -150,10 +148,10 @@ void FeedbackUser::jobs_to_submit(
     update_date_next_sub();   
 }
 
-void FeedbackUser::wake_on_feedback(double date, std::list<Job *> &ended_jobs)
+void FeedbackUser::wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs)
 {
     /* Propagate the info and close finished sessions */
-    for (Job *j : ended_jobs)
+    for (shared_ptr<Job>j : ended_jobs)
     {
         j->session->unfinished_jobs--;
         PPK_ASSERT_ERROR(ongoing_job_counter > 0,
@@ -208,7 +206,7 @@ void FBUserThinkTimeOnly::close_session(double date, Session *finished_session)
     delete finished_session;
 }
 
-bool FBUserThinkTimeOnly::handle_job(double date, Job *job, Profile *profile)
+bool FBUserThinkTimeOnly::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     Parser::profile_from_duration(
         profile, job->profile, user_name, platform_computing_speed);
diff --git a/src/users/user_feedback.hpp b/src/users/user_feedback.hpp
index 4a60ae0a15747daa0d6f9fcbb8e4a529d5b95336..311dc0439d42a6bc1128501c00e0c9d34ccb5606 100644
--- a/src/users/user_feedback.hpp
+++ b/src/users/user_feedback.hpp
@@ -17,8 +17,8 @@ public:
     virtual ~FeedbackUser();
     double next_submission();
     virtual void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
-    virtual void wake_on_feedback(double date, std::list<Job *> &ended_jobs);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
+    virtual void wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs);
 
 protected:
     /**
@@ -44,7 +44,7 @@ protected:
      * depending on the user behavior and returns if it should still be executed
      * now.
      */
-    virtual bool handle_job(double date, Job *job, Profile *profile) = 0;
+    virtual bool handle_job(double date, shared_ptr<Job>job, Profile *profile) = 0;
 
 protected:
     std::string input_json;
@@ -80,5 +80,5 @@ public:
 
 protected:
     void close_session(double date, Session *finished_session);
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job> job, Profile *profile);
 };
\ No newline at end of file
diff --git a/src/users/user_model.cpp b/src/users/user_model.cpp
index 17c0457893fc2c8bc6b66ec974d7ea3a5106cb44..f8c53525dd067b880de2ff55ccb4f4862cb25dd4 100644
--- a/src/users/user_model.cpp
+++ b/src/users/user_model.cpp
@@ -39,12 +39,12 @@ DichoIntersubmitTimeUser::~DichoIntersubmitTimeUser()
 }
 
 void DichoIntersubmitTimeUser::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
-    jobs = std::list<Job *>();
+    jobs = std::list<shared_ptr<Job>>();
 
     /* The last job is still running */
-    if (last_job_submitted != nullptr
+    if (last_job_submitted 
         && (last_job_submitted->status == WAITING
             || last_job_submitted->status == RUNNING))
     {
@@ -55,7 +55,7 @@ void DichoIntersubmitTimeUser::jobs_to_submit(
     else
     {
         /* First job submitted by this user */
-        if (last_job_submitted == nullptr)
+        if (!last_job_submitted)
         {
             delay_between_sumbit = delay_sup; // initial delay
             profiles = job_profiles_used();
@@ -65,10 +65,10 @@ void DichoIntersubmitTimeUser::jobs_to_submit(
         {
             delay_sup = std::ceil(date - last_job_submitted->submission_time);
             delay_between_sumbit = (delay_sup + delay_inf) / 2;
-            profiles = std::list<Profile *>(); // already submitted before
+            profiles = std::list<const Profile *>(); // already submitted before
         }
 
-        Job *job = new Job();
+        shared_ptr<Job>job = shared_ptr<Job>(new Job());
         job->id = user_name + "!" + std::to_string(job_id++);
         job->profile = "100_sec";
         job->submission_time = date;
@@ -88,9 +88,9 @@ void DichoIntersubmitTimeUser::jobs_to_submit(
         date_of_next_submission = DATE_NEVER;
 }
 
-std::list<Profile *> DichoIntersubmitTimeUser::job_profiles_used()
+std::list<const Profile *> DichoIntersubmitTimeUser::job_profiles_used()
 {
-    std::list<Profile *> profiles;
+    std::list<const Profile *> profiles;
 
     Profile *profile0 = new Profile();
     profile0->workload_name = user_name;
@@ -142,22 +142,36 @@ RoutineGreedyUser::~RoutineGreedyUser()
 {
 }
 
-bool RoutineGreedyUser::all_jobs_finished_successfully() const
+bool RoutineGreedyUser::previous_jobs_succedded()
 {
-    for (const Job *job : last_jobs_submitted)
+    bool res = true;
+    for (auto iter = last_jobs_submitted.begin(); 
+        iter != last_jobs_submitted.end();)
     {
-        if (job->status == WAITING || job->status == RUNNING 
-            || job->status == KILLED)
-            return false;
+        shared_ptr<Job> job = *iter;
+
+        switch (job->status) {
+            case WAITING: 
+            case RUNNING:
+                res = false;
+                iter++;
+                break;
+            case KILLED:
+                res = false;
+                iter = last_jobs_submitted.erase(iter);
+                break;
+            case FINISHED:
+                iter = last_jobs_submitted.erase(iter);
+        }
     }
-    return true;
+    return res;
 }
 
 void RoutineGreedyUser::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
-    jobs = std::list<Job *>();
-    profiles = std::list<Profile *>();
+    jobs = std::list<shared_ptr<Job>>();
+    profiles = std::list<const Profile *>();
 
     /* First call: just submit the initial amount of jobs */
     if (first_submit)
@@ -167,7 +181,7 @@ void RoutineGreedyUser::jobs_to_submit(
     }
 
     /* All job finished: submit twice as many jobs */
-    else if (all_jobs_finished_successfully())
+    else if (previous_jobs_succedded())
         nb_jobs_to_submit
             = (nb_jobs_to_submit == 0) ? 1 : nb_jobs_to_submit * 2;
 
@@ -175,10 +189,9 @@ void RoutineGreedyUser::jobs_to_submit(
     else
         nb_jobs_to_submit /= 2;
 
-    last_jobs_submitted.clear();
     for (int i = 0; i < nb_jobs_to_submit; i++)
     {
-        Job *job = new Job();
+        shared_ptr<Job> job = shared_ptr<Job>(new Job());
         job->id = user_name + "!" + std::to_string(job_id++);
         job->profile = "100_sec";
         job->submission_time = date;
@@ -198,9 +211,9 @@ void RoutineGreedyUser::jobs_to_submit(
         date_of_next_submission = DATE_NEVER;
 }
 
-std::list<Profile *> RoutineGreedyUser::job_profiles_used()
+std::list<const Profile *> RoutineGreedyUser::job_profiles_used()
 {
-    std::list<Profile *> profiles;
+    std::list<const Profile *> profiles;
 
     Profile *profile0 = new Profile();
     profile0->workload_name = user_name;
@@ -246,9 +259,9 @@ ThinkTimeUser::~ThinkTimeUser()
 }
 
 void ThinkTimeUser::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
-    jobs = std::list<Job *>();
+    jobs = std::list<shared_ptr<Job>>();
 
     /* Stop condition reached */
     if (date > end_submit)
@@ -258,9 +271,15 @@ void ThinkTimeUser::jobs_to_submit(
     else
     {
         /* First job submitted by this user */
-        if (last_job_submitted == nullptr)
+        if (!last_job_submitted)
             profiles = job_profiles_used();
-        Job *job = new Job();
+        else{
+            PPK_ASSERT_ERROR(last_job_submitted->status == FINISHED
+                || last_job_submitted->status == KILLED,
+                "ThinkTimeUser %s called to submit, but her last job did not finish", user_name.c_str());
+        }
+
+        shared_ptr<Job> job = shared_ptr<Job>(new Job());
         job->id = user_name + "!" + std::to_string(job_id++);
         job->profile = "100_sec";
         job->submission_time = date;
@@ -271,13 +290,13 @@ void ThinkTimeUser::jobs_to_submit(
         jobs.push_back(job);
 
         /* Date of next submission unknown for now... */
-        date_of_next_submission = -2.0;
+        date_of_next_submission = DATE_UNKNOWN;
     }
 }
 
-std::list<Profile *> ThinkTimeUser::job_profiles_used()
+std::list<const Profile *> ThinkTimeUser::job_profiles_used()
 {
-    std::list<Profile *> profiles;
+    std::list<const Profile *> profiles;
 
     Profile *profile0 = new Profile();
     profile0->workload_name = user_name;
@@ -291,7 +310,7 @@ std::list<Profile *> ThinkTimeUser::job_profiles_used()
     return profiles;
 }
 
-void ThinkTimeUser::wake_on_feedback(double date, std::list<Job *> &ended_jobs)
+void ThinkTimeUser::wake_on_feedback(double date, std::list<shared_ptr<Job>> &ended_jobs)
 {
     /* The user has been awakened: her last job terminated */
     PPK_ASSERT_ERROR(last_job_submitted->status == KILLED
diff --git a/src/users/user_model.hpp b/src/users/user_model.hpp
index f593986bf86a7ddb6014f0885799dc4860d2e971..7ad4663919a175df5b89059e68f437018eedb4e9 100644
--- a/src/users/user_model.hpp
+++ b/src/users/user_model.hpp
@@ -9,23 +9,23 @@
 class DichoIntersubmitTimeUser : public User
 {
 public:
-    DichoIntersubmitTimeUser(std::string name, double date_first_submit,
+    DichoIntersubmitTimeUser(string name, double date_first_submit,
         double date_end_submit, double initial_delay);
-    DichoIntersubmitTimeUser(std::string name, const rapidjson::Value &param);
+    DichoIntersubmitTimeUser(string name, const rapidjson::Value &param);
     ~DichoIntersubmitTimeUser();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles);
 
 protected:
-    std::list<Profile *> job_profiles_used();
+    list<const Profile *> job_profiles_used();
 
 private:
     double delay_inf = 0;
     double delay_sup;
     double delay_between_sumbit;
     int job_id = 0;
-    const Job *last_job_submitted = nullptr;
+    shared_ptr<Job> last_job_submitted;
 };
 
 /**
@@ -37,17 +37,17 @@ private:
 class RoutineGreedyUser : public User
 {
 public:
-    RoutineGreedyUser(std::string name, double date_first_submit,
+    RoutineGreedyUser(string name, double date_first_submit,
         double date_end_submit, double delay_between_sumbit,
         int initial_nb_job);
-    RoutineGreedyUser(std::string name, const rapidjson::Value &param);
+    RoutineGreedyUser(string name, const rapidjson::Value &param);
     ~RoutineGreedyUser();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles);
 
 protected:
-    std::list<Profile *> job_profiles_used();
+    list<const Profile *> job_profiles_used();
 
 private:
     double delay_between_sumbit;
@@ -55,8 +55,10 @@ private:
     bool first_submit = true;
 
     int job_id = 0;
-    std::list<const Job *> last_jobs_submitted;
-    bool all_jobs_finished_successfully() const;
+    list<shared_ptr<Job>> last_jobs_submitted;
+    /* Return true if all the jobs previously submitted by the user finished
+     * successfully. Also delete the finished jobs. */
+    bool previous_jobs_succedded();
 };
 
 /**
@@ -69,20 +71,20 @@ private:
 class ThinkTimeUser : public User
 {
 public:
-    ThinkTimeUser(std::string name, double date_first_submit,
+    ThinkTimeUser(string name, double date_first_submit,
         double date_end_submit, double think_time);
-    ThinkTimeUser(std::string name, const rapidjson::Value &param);
+    ThinkTimeUser(string name, const rapidjson::Value &param);
     ~ThinkTimeUser();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
-    void wake_on_feedback(double date, std::list<Job *> &ended_jobs);
+        double date, list<shared_ptr<Job>> &jobs, list<const Profile *> &profiles);
+    void wake_on_feedback(double date, list<shared_ptr<Job>> &ended_jobs);
 
 protected:
-    std::list<Profile *> job_profiles_used();
+    list<const Profile *> job_profiles_used();
 
 private:
     double think_time;
     int job_id = 0;
-    Job *last_job_submitted = nullptr;
+    shared_ptr<Job> last_job_submitted;
 };
\ No newline at end of file
diff --git a/src/users/user_replay.cpp b/src/users/user_replay.cpp
index 878d8240c62441e1f2448790041392e3d88b04ee..7ccb4208d4ed75abc7f573becfc193c4dace636f 100644
--- a/src/users/user_replay.cpp
+++ b/src/users/user_replay.cpp
@@ -35,25 +35,25 @@ ReplayUser::~ReplayUser()
 }
 
 void ReplayUser::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
-    jobs = std::list<Job *>();
-    profiles = std::list<Profile *>();
+    jobs = std::list<shared_ptr<Job>>();
+    profiles = std::list<const Profile *>();
 
     PPK_ASSERT_ERROR(!original_trace->is_empty(),
         "User %s has been called to sumbit but her job queue is empty",
         user_name.c_str());
-    PPK_ASSERT_ERROR(original_trace->first_job()->submission_time <= date,
-        "First job in user %s's queue has greater sumbmission time than "
-        "current date",
-        user_name.c_str());
+    PPK_ASSERT_ERROR(original_trace->first_job()->submission_time < date + EPSILON,
+        "First job in user %s's queue has greater sumbmission time (%f) than "
+        "current date (%f)",
+        user_name.c_str(), original_trace->first_job()->submission_time, date);
 
     /* Submit all jobs that have same submit time */
     while (!original_trace->is_empty()
-        && original_trace->first_job()->submission_time <= date)
+        && original_trace->first_job()->submission_time < date + EPSILON)
     {
         /* Cast const Job * into Job * */
-        Job *job = new Job(*original_trace->first_job());
+        shared_ptr<Job> job = shared_ptr<Job>(new Job(*original_trace->first_job()));
         Profile *job_profile = new Profile();
 
         /* Handle the job according to the user behavior. */
@@ -100,12 +100,12 @@ ReplayUserRigid::~ReplayUserRigid()
 }
 
 void ReplayUserRigid::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
     ReplayUser::jobs_to_submit(date, jobs, profiles);
 }
 
-bool ReplayUserRigid::handle_job(double date, Job *job, Profile *profile)
+bool ReplayUserRigid::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     /* Just generate the corresponding profile */
     Parser::profile_from_duration(profile, job->profile, user_name, platform_computing_speed);
@@ -121,7 +121,7 @@ bool ReplayUserRigid::handle_job(double date, Job *job, Profile *profile)
 }
 
 /* ReplayUserReconfig */
-bool ReplayUserReconfig::handle_job(double date, Job *job, Profile *profile)
+bool ReplayUserReconfig::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     int orig_nb_core = job->nb_requested_resources;
 
@@ -204,7 +204,7 @@ ReplayUserReconfig::~ReplayUserReconfig()
 }
 
 void ReplayUserReconfig::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
     ReplayUser::jobs_to_submit(date, jobs, profiles);
 }
@@ -253,7 +253,7 @@ DMUserReconfig::~DMUserReconfig()
 }
 
 void DMUserReconfig::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
     ReplayUser::jobs_to_submit(date, jobs, profiles);
 }
@@ -271,7 +271,7 @@ DMUserDegrad::~DMUserDegrad()
 }
 
 void DMUserDegrad::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
     ReplayUser::jobs_to_submit(date, jobs, profiles);
 }
@@ -289,7 +289,7 @@ DMUserRenonce::~DMUserRenonce()
 }
 
 void DMUserRenonce::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
     ReplayUser::jobs_to_submit(date, jobs, profiles);
 }
@@ -307,12 +307,12 @@ DMUserDelay::~DMUserDelay()
 }
 
 void DMUserDelay::jobs_to_submit(
-    double date, std::list<Job *> &jobs, std::list<Profile *> &profiles)
+    double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles)
 {
     ReplayUser::jobs_to_submit(date, jobs, profiles);
 }
 
-bool DMUserReconfig::handle_job(double date, Job *job, Profile *profile)
+bool DMUserReconfig::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     if (dm_window->date_in_dm_window(date))
     {
@@ -356,7 +356,7 @@ bool DMUserReconfig::handle_job(double date, Job *job, Profile *profile)
     return true;
 }
 
-bool DMUserDegrad::handle_job(double date, Job *job, Profile *profile)
+bool DMUserDegrad::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     if (dm_window->date_in_dm_window(date))
     {
@@ -390,7 +390,7 @@ bool DMUserDegrad::handle_job(double date, Job *job, Profile *profile)
     return true;
 }
 
-bool DMUserRenonce::handle_job(double date, Job *job, Profile *profile)
+bool DMUserRenonce::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     if (dm_window->date_in_dm_window(date))
     {
@@ -411,7 +411,7 @@ bool DMUserRenonce::handle_job(double date, Job *job, Profile *profile)
     return true;
 }
 
-bool DMUserDelay::handle_job(double date, Job *job, Profile *profile)
+bool DMUserDelay::handle_job(double date, shared_ptr<Job>job, Profile *profile)
 {
     if (dm_window->date_in_dm_window(date))
     {
@@ -425,7 +425,8 @@ bool DMUserDelay::handle_job(double date, Job *job, Profile *profile)
 
         /* Put job back in the queue and sort */
         SortableJobOrder::UpdateInformation update_info(0);
-        original_trace->insert_job(job);
+        Job *j = new Job(); *j = *job;
+        original_trace->insert_job(j);
         original_trace->sort_queue(&update_info);
 
         /* Return "Do not execute now" */
diff --git a/src/users/user_replay.hpp b/src/users/user_replay.hpp
index 55b80f25497ce17c2ef6ee70a2625b7e6c27c48a..2be3beb4102898651060114a0aa041ed7393f943 100644
--- a/src/users/user_replay.hpp
+++ b/src/users/user_replay.hpp
@@ -24,7 +24,7 @@ public:
     virtual ~ReplayUser();
     double next_submission();
     virtual void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
     /**
@@ -38,7 +38,7 @@ protected:
      * A job is read in the original trace. Handle it depending on the user
      * behavior and returns if it should still be executed now.
      */
-    virtual bool handle_job(double date, Job *job, Profile *profile) = 0;
+    virtual bool handle_job(double date, shared_ptr<Job>job, Profile *profile) = 0;
     virtual int *get_dm_stat();
 
 protected:
@@ -63,10 +63,10 @@ public:
     ~ReplayUserRigid();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job>job, Profile *profile);
 };
 
 /**
@@ -84,13 +84,13 @@ public:
     ~ReplayUserReconfig();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
     /** Draw a random variable according to the proportions given by
      * big_medium_little and reconfigure the number of cores requested
      * accordingly. */
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job>job, Profile *profile);
 
 private:
     double big, medium, little;
@@ -127,10 +127,10 @@ public:
     ~DMUserReconfig();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job>job, Profile *profile);
     double alpha = 1.0; // for the speedup model 
 };
 
@@ -146,10 +146,10 @@ public:
     ~DMUserDegrad();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job>job, Profile *profile);
 };
 
 /**
@@ -164,10 +164,10 @@ public:
     ~DMUserRenonce();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job>job, Profile *profile);
 };
 
 /**
@@ -182,8 +182,8 @@ public:
     ~DMUserDelay();
     double next_submission();
     void jobs_to_submit(
-        double date, std::list<Job *> &jobs, std::list<Profile *> &profiles);
+        double date, std::list<shared_ptr<Job>> &jobs, std::list<const Profile *> &profiles);
 
 protected:
-    bool handle_job(double date, Job *job, Profile *profile);
+    bool handle_job(double date, shared_ptr<Job>job, Profile *profile);
 };
\ No newline at end of file