Bug Summary

File:/tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/core/model/simulator.cc
Location:line 173, column 9
Description:Called C++ object pointer is null

Annotated Source Code

1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005,2006 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20#include "ns3/core-config.h"
21#include "simulator.h"
22#include "simulator-impl.h"
23#include "scheduler.h"
24#include "map-scheduler.h"
25#include "event-impl.h"
26#include "des-metrics.h"
27
28#include "ptr.h"
29#include "string.h"
30#include "object-factory.h"
31#include "global-value.h"
32#include "assert.h"
33#include "log.h"
34
35#include <cmath>
36#include <fstream>
37#include <list>
38#include <vector>
39#include <iostream>
40#include <iomanip>
41
42/**
43 * \file
44 * \ingroup simulator
45 * ns3::Simulator implementation, as well as implementation pointer,
46 * global scheduler implementation, and default ns3::NodePrinter
47 * and ns3::TimePrinter.
48 */
49
50namespace ns3 {
51
52// Note: Logging in this file is largely avoided due to the
53// number of calls that are made to these functions and the possibility
54// of causing recursions leading to stack overflow
55NS_LOG_COMPONENT_DEFINE ("Simulator")static ns3::LogComponent g_log = ns3::LogComponent ("Simulator"
, "../src/core/model/simulator.cc")
;
56
57/**
58 * \ingroup simulator
59 * The specific simulator implementation to use.
60 *
61 * Must be derived from SimulatorImpl.
62 */
63static GlobalValue g_simTypeImpl = GlobalValue
64 ("SimulatorImplementationType",
65 "The object class to use as the simulator implementation",
66 StringValue ("ns3::DefaultSimulatorImpl"),
67 MakeStringChecker ());
68
69/**
70 * \ingroup scheduler
71 * The specific event scheduler implementation to use.
72 *
73 * Must be derived from Scheduler.
74 */
75static GlobalValue g_schedTypeImpl = GlobalValue ("SchedulerType",
76 "The object class to use as the scheduler implementation",
77 TypeIdValue (MapScheduler::GetTypeId ()),
78 MakeTypeIdChecker ());
79
80/**
81 * \ingroup logging
82 * Default TimePrinter implementation.
83 *
84 * \param [in,out] os The output stream to print the time on.
85 */
86static void
87TimePrinter (std::ostream &os)
88{
89 std::ios_base::fmtflags ff = os.flags (); // Save stream flags
90 std::streamsize oldPrecision = os.precision ();
91 if (Time::GetResolution () == Time::NS)
92 {
93 os << std::fixed << std::setprecision (9) << Simulator::Now ().As (Time::S);
94 }
95 else if (Time::GetResolution () == Time::PS)
96 {
97 os << std::fixed << std::setprecision (12) << Simulator::Now ().As (Time::S);
98 }
99 else if (Time::GetResolution () == Time::FS)
100 {
101 os << std::fixed << std::setprecision (15) << Simulator::Now ().As (Time::S);
102 }
103 else if (Time::GetResolution () == Time::US)
104 {
105 os << std::fixed << std::setprecision (6) << Simulator::Now ().As (Time::S);
106 }
107 else
108 {
109 // default C++ precision of 5
110 os << std::fixed << std::setprecision (5) << Simulator::Now ().As (Time::S);
111 }
112 os << std::setprecision (oldPrecision);
113 os.flags (ff); // Restore stream flags
114}
115
116/**
117 * \ingroup logging
118 * Default node id printer implementation.
119 *
120 * \param [in,out] os The output stream to print the node id on.
121 */
122static void
123NodePrinter (std::ostream &os)
124{
125 if (Simulator::GetContext () == Simulator::NO_CONTEXT)
1
Calling 'Simulator::GetContext'
126 {
127 os << "-1";
128 }
129 else
130 {
131 os << Simulator::GetContext ();
132 }
133}
134
135/**
136 * \ingroup simulator
137 * \brief Get the static SimulatorImpl instance.
138 * \return The SimulatorImpl instance pointer.
139 */
140static SimulatorImpl **PeekImpl (void)
141{
142 static SimulatorImpl *impl = 0;
143 return &impl;
144}
145
146/**
147 * \ingroup simulator
148 * \brief Get the SimulatorImpl singleton.
149 * \return The singleton pointer.
150 * \see Simulator::GetImplementation()
151 */
152static SimulatorImpl * GetImpl (void)
153{
154 SimulatorImpl **pimpl = PeekImpl ();
155 /* Please, don't include any calls to logging macros in this function
156 * or pay the price, that is, stack explosions.
157 */
158 if (*pimpl == 0)
3
Taking true branch
159 {
160 {
161 ObjectFactory factory;
162 StringValue s;
163
164 g_simTypeImpl.GetValue (s);
165 factory.SetTypeId (s.Get ());
166 *pimpl = GetPointer (factory.Create<SimulatorImpl> ());
167 }
168 {
169 ObjectFactory factory;
170 StringValue s;
171 g_schedTypeImpl.GetValue (s);
172 factory.SetTypeId (s.Get ());
173 (*pimpl)->SetScheduler (factory);
4
Called C++ object pointer is null
174 }
175
176//
177// Note: we call LogSetTimePrinter _after_ creating the implementation
178// object because the act of creation can trigger calls to the logging
179// framework which would call the TimePrinter function which would call
180// Simulator::Now which would call Simulator::GetImpl, and, thus, get us
181// in an infinite recursion until the stack explodes.
182//
183 LogSetTimePrinter (&TimePrinter);
184 LogSetNodePrinter (&NodePrinter);
185 }
186 return *pimpl;
187}
188
189void
190Simulator::Destroy (void)
191{
192 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
193
194 SimulatorImpl **pimpl = PeekImpl ();
195 if (*pimpl == 0)
196 {
197 return;
198 }
199 /* Note: we have to call LogSetTimePrinter (0) below because if we do not do
200 * this, and restart a simulation after this call to Destroy, (which is
201 * legal), Simulator::GetImpl will trigger again an infinite recursion until
202 * the stack explodes.
203 */
204 LogSetTimePrinter (0);
205 LogSetNodePrinter (0);
206 (*pimpl)->Destroy ();
207 (*pimpl)->Unref ();
208 *pimpl = 0;
209}
210
211void
212Simulator::SetScheduler (ObjectFactory schedulerFactory)
213{
214 NS_LOG_FUNCTION (schedulerFactory)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
schedulerFactory; std::clog << ")" << std::endl;
} } while (false)
;
215 GetImpl ()->SetScheduler (schedulerFactory);
216}
217
218bool
219Simulator::IsFinished (void)
220{
221 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
222 return GetImpl ()->IsFinished ();
223}
224
225void
226Simulator::Run (void)
227{
228 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
229 Time::ClearMarkedTimes ();
230 GetImpl ()->Run ();
231}
232
233void
234Simulator::Stop (void)
235{
236 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
237 NS_LOG_LOGIC ("stop")do { if (g_log.IsEnabled (ns3::LOG_LOGIC)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_LOGIC) << "] "; }; std::clog << "stop" <<
std::endl; } } while (false)
;
238 GetImpl ()->Stop ();
239}
240
241void
242Simulator::Stop (Time const &delay)
243{
244 NS_LOG_FUNCTION (delay)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
delay; std::clog << ")" << std::endl; } } while (
false)
;
245 GetImpl ()->Stop (delay);
246}
247
248Time
249Simulator::Now (void)
250{
251 /* Please, don't include any calls to logging macros in this function
252 * or pay the price, that is, stack explosions.
253 */
254 return GetImpl ()->Now ();
255}
256
257Time
258Simulator::GetDelayLeft (const EventId &id)
259{
260 NS_LOG_FUNCTION (&id)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
&id; std::clog << ")" << std::endl; } } while
(false)
;
261 return GetImpl ()->GetDelayLeft (id);
262}
263
264EventId
265Simulator::Schedule (Time const &delay, const Ptr<EventImpl> &event)
266{
267 return DoSchedule (delay, GetPointer (event));
268}
269
270EventId
271Simulator::ScheduleNow (const Ptr<EventImpl> &ev)
272{
273 return DoScheduleNow (GetPointer (ev));
274}
275void
276Simulator::ScheduleWithContext (uint32_t context, const Time &delay, EventImpl *impl)
277{
278#ifdef ENABLE_DES_METRICS
279 DesMetrics::Get ()->TraceWithContext (context, Now (), delay);
280#endif
281 return GetImpl ()->ScheduleWithContext (context, delay, impl);
282}
283EventId
284Simulator::ScheduleDestroy (const Ptr<EventImpl> &ev)
285{
286 return DoScheduleDestroy (GetPointer (ev));
287}
288EventId
289Simulator::DoSchedule (Time const &time, EventImpl *impl)
290{
291#ifdef ENABLE_DES_METRICS
292 DesMetrics::Get ()->Trace (Now (), time);
293#endif
294 return GetImpl ()->Schedule (time, impl);
295}
296EventId
297Simulator::DoScheduleNow (EventImpl *impl)
298{
299#ifdef ENABLE_DES_METRICS
300 DesMetrics::Get ()->Trace (Now (), Time (0));
301#endif
302 return GetImpl ()->ScheduleNow (impl);
303}
304EventId
305Simulator::DoScheduleDestroy (EventImpl *impl)
306{
307 return GetImpl ()->ScheduleDestroy (impl);
308}
309
310
311EventId
312Simulator::Schedule (Time const &delay, void (*f)(void))
313{
314 return DoSchedule (delay, MakeEvent (f));
315}
316
317void
318Simulator::ScheduleWithContext (uint32_t context, Time const &delay, void (*f)(void))
319{
320 return ScheduleWithContext (context, delay, MakeEvent (f));
321}
322
323EventId
324Simulator::ScheduleNow (void (*f)(void))
325{
326 return DoScheduleNow (MakeEvent (f));
327}
328
329EventId
330Simulator::ScheduleDestroy (void (*f)(void))
331{
332 return DoScheduleDestroy (MakeEvent (f));
333}
334
335void
336Simulator::Remove (const EventId &id)
337{
338 if (*PeekImpl () == 0)
339 {
340 return;
341 }
342 return GetImpl ()->Remove (id);
343}
344
345void
346Simulator::Cancel (const EventId &id)
347{
348 if (*PeekImpl () == 0)
349 {
350 return;
351 }
352 return GetImpl ()->Cancel (id);
353}
354
355bool
356Simulator::IsExpired (const EventId &id)
357{
358 if (*PeekImpl () == 0)
359 {
360 return true;
361 }
362 return GetImpl ()->IsExpired (id);
363}
364
365Time Now (void)
366{
367 return Time (Simulator::Now ());
368}
369
370Time
371Simulator::GetMaximumSimulationTime (void)
372{
373 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
374 return GetImpl ()->GetMaximumSimulationTime ();
375}
376
377uint32_t
378Simulator::GetContext (void)
379{
380 return GetImpl ()->GetContext ();
2
Calling 'GetImpl'
381}
382
383uint32_t
384Simulator::GetSystemId (void)
385{
386 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
387
388 if (*PeekImpl () != 0)
389 {
390 return GetImpl ()->GetSystemId ();
391 }
392 else
393 {
394 return 0;
395 }
396}
397
398void
399Simulator::SetImplementation (Ptr<SimulatorImpl> impl)
400{
401 NS_LOG_FUNCTION (impl)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
impl; std::clog << ")" << std::endl; } } while (
false)
;
402 if (*PeekImpl () != 0)
403 {
404 NS_FATAL_ERROR ("It is not possible to set the implementation after calling any Simulator:: function. Call Simulator::SetImplementation earlier or after Simulator::Destroy.")do { std::cerr << "msg=\"" << "It is not possible to set the implementation after calling any Simulator:: function. Call Simulator::SetImplementation earlier or after Simulator::Destroy."
<< "\", "; do { std::cerr << "file=" << "../src/core/model/simulator.cc"
<< ", line=" << 404 << std::endl; ::ns3::FatalImpl
::FlushStreams (); if (true) std::terminate (); } while (false
); } while (false)
;
405 }
406 *PeekImpl () = GetPointer (impl);
407 // Set the default scheduler
408 ObjectFactory factory;
409 StringValue s;
410 g_schedTypeImpl.GetValue (s);
411 factory.SetTypeId (s.Get ());
412 impl->SetScheduler (factory);
413//
414// Note: we call LogSetTimePrinter _after_ creating the implementation
415// object because the act of creation can trigger calls to the logging
416// framework which would call the TimePrinter function which would call
417// Simulator::Now which would call Simulator::GetImpl, and, thus, get us
418// in an infinite recursion until the stack explodes.
419//
420 LogSetTimePrinter (&TimePrinter);
421 LogSetNodePrinter (&NodePrinter);
422}
423
424Ptr<SimulatorImpl>
425Simulator::GetImplementation (void)
426{
427 NS_LOG_FUNCTION_NOARGS ()do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "()" << std::endl; } } while (false
)
;
428 return GetImpl ();
429}
430
431
432
433} // namespace ns3
434