Bug Summary

File:/tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/core/model/object.cc
Location:line 424, column 14
Description:Attempt to delete released memory

Annotated Source Code

1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2007 INRIA, Gustavo Carneiro
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 * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
19 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20 */
21
22#include "object.h"
23#include "object-factory.h"
24#include "assert.h"
25#include "attribute.h"
26#include "log.h"
27#include "string.h"
28#include <vector>
29#include <sstream>
30#include <cstdlib>
31#include <cstring>
32
33/**
34 * \file
35 * \ingroup object
36 * ns3::Object class implementation.
37 */
38
39namespace ns3 {
40
41NS_LOG_COMPONENT_DEFINE ("Object")static ns3::LogComponent g_log = ns3::LogComponent ("Object",
"../src/core/model/object.cc")
;
42
43/*********************************************************************
44 * The Object implementation
45 *********************************************************************/
46
47NS_OBJECT_ENSURE_REGISTERED (Object)static struct ObjectObjectRegistrationClass { ObjectObjectRegistrationClass
() { ns3::TypeId tid = Object::GetTypeId (); tid.SetSize (sizeof
(Object)); tid.GetParent (); } } ObjectObjectRegistrationVariable
;
48
49Object::AggregateIterator::AggregateIterator ()
50 : m_object (0),
51 m_current (0)
52{
53 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
54}
55
56bool
57Object::AggregateIterator::HasNext (void) const
58{
59 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
60 return m_current < m_object->m_aggregates->n;
61}
62Ptr<const Object>
63Object::AggregateIterator::Next (void)
64{
65 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
66 Object *object = m_object->m_aggregates->buffer[m_current];
67 m_current++;
68 return object;
69}
70Object::AggregateIterator::AggregateIterator (Ptr<const Object> object)
71 : m_object (object),
72 m_current (0)
73{
74 NS_LOG_FUNCTION (this << object)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) <<
this << object; std::clog << ")" << std::endl
; } } while (false)
;
75}
76
77
78TypeId
79Object::GetInstanceTypeId (void) const
80{
81 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
82 return m_tid;
83}
84
85TypeId
86Object::GetTypeId (void)
87{
88 static TypeId tid = TypeId ("ns3::Object")
89 .SetParent<ObjectBase> ()
90 .SetGroupName ("Core")
91 ;
92 return tid;
93}
94
95
96Object::Object ()
97 : m_tid (Object::GetTypeId ()),
98 m_disposed (false),
99 m_initialized (false),
100 m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
101 m_getObjectCount (0)
102{
103 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
104 m_aggregates->n = 1;
105 m_aggregates->buffer[0] = this;
106}
107Object::~Object ()
108{
109 // remove this object from the aggregate list
110 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
111 uint32_t n = m_aggregates->n;
112 for (uint32_t i = 0; i < n; i++)
113 {
114 Object *current = m_aggregates->buffer[i];
115 if (current == this)
116 {
117 std::memmove (&m_aggregates->buffer[i],
118 &m_aggregates->buffer[i+1],
119 sizeof (Object *)*(m_aggregates->n - (i+1)));
120 m_aggregates->n--;
121 }
122 }
123 // finally, if all objects have been removed from the list,
124 // delete the aggregate list
125 if (m_aggregates->n == 0)
126 {
127 std::free (m_aggregates);
128 }
129 m_aggregates = 0;
130}
131Object::Object (const Object &o)
132 : m_tid (o.m_tid),
133 m_disposed (false),
134 m_initialized (false),
135 m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
136 m_getObjectCount (0)
137{
138 m_aggregates->n = 1;
139 m_aggregates->buffer[0] = this;
140}
141void
142Object::Construct (const AttributeConstructionList &attributes)
143{
144 NS_LOG_FUNCTION (this << &attributes)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) <<
this << &attributes; std::clog << ")" <<
std::endl; } } while (false)
;
145 ConstructSelf (attributes);
146}
147
148Ptr<Object>
149Object::DoGetObject (TypeId tid) const
150{
151 NS_LOG_FUNCTION (this << tid)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) <<
this << tid; std::clog << ")" << std::endl
; } } while (false)
;
152 NS_ASSERT (CheckLoose ())do { if (!(CheckLoose ())) { std::cerr << "assert failed. cond=\""
<< "CheckLoose ()" << "\", "; do { std::cerr <<
"file=" << "../src/core/model/object.cc" << ", line="
<< 152 << std::endl; ::ns3::FatalImpl::FlushStreams
(); if (true) std::terminate (); } while (false); } } while (
false)
;
153
154 uint32_t n = m_aggregates->n;
155 TypeId objectTid = Object::GetTypeId ();
156 for (uint32_t i = 0; i < n; i++)
157 {
158 Object *current = m_aggregates->buffer[i];
159 TypeId cur = current->GetInstanceTypeId ();
160 while (cur != tid && cur != objectTid)
161 {
162 cur = cur.GetParent ();
163 }
164 if (cur == tid)
165 {
166 // This is an attempt to 'cache' the result of this lookup.
167 // the idea is that if we perform a lookup for a TypeId on this object,
168 // we are likely to perform the same lookup later so, we make sure
169 // that the aggregate array is sorted by the number of accesses
170 // to each object.
171
172 // first, increment the access count
173 current->m_getObjectCount++;
174 // then, update the sort
175 UpdateSortedArray (m_aggregates, i);
176 // finally, return the match
177 return const_cast<Object *> (current);
178 }
179 }
180 return 0;
181}
182void
183Object::Initialize (void)
184{
185 /**
186 * Note: the code here is a bit tricky because we need to protect ourselves from
187 * modifications in the aggregate array while DoInitialize is called. The user's
188 * implementation of the DoInitialize method could call GetObject (which could
189 * reorder the array) and it could call AggregateObject which would add an
190 * object at the end of the array. To be safe, we restart iteration over the
191 * array whenever we call some user code, just in case.
192 */
193 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
194restart:
195 uint32_t n = m_aggregates->n;
196 for (uint32_t i = 0; i < n; i++)
197 {
198 Object *current = m_aggregates->buffer[i];
199 if (!current->m_initialized)
200 {
201 current->DoInitialize ();
202 current->m_initialized = true;
203 goto restart;
204 }
205 }
206}
207bool
208Object::IsInitialized (void) const
209{
210 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
211 return m_initialized;
212}
213void
214Object::Dispose (void)
215{
216 /**
217 * Note: the code here is a bit tricky because we need to protect ourselves from
218 * modifications in the aggregate array while DoDispose is called. The user's
219 * DoDispose implementation could call GetObject (which could reorder the array)
220 * and it could call AggregateObject which would add an object at the end of the array.
221 * So, to be safe, we restart the iteration over the array whenever we call some
222 * user code.
223 */
224 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
225restart:
226 uint32_t n = m_aggregates->n;
227 for (uint32_t i = 0; i < n; i++)
228 {
229 Object *current = m_aggregates->buffer[i];
230 if (!current->m_disposed)
231 {
232 current->DoDispose ();
233 current->m_disposed = true;
234 goto restart;
235 }
236 }
237}
238void
239Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
240{
241 NS_LOG_FUNCTION (this << aggregates << j)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) <<
this << aggregates << j; std::clog << ")" <<
std::endl; } } while (false)
;
242 while (j > 0 &&
243 aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
244 {
245 Object *tmp = aggregates->buffer[j-1];
246 aggregates->buffer[j-1] = aggregates->buffer[j];
247 aggregates->buffer[j] = tmp;
248 j--;
249 }
250}
251void
252Object::AggregateObject (Ptr<Object> o)
253{
254 NS_LOG_FUNCTION (this << o)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) <<
this << o; std::clog << ")" << std::endl; }
} while (false)
;
255 NS_ASSERT (!m_disposed)do { if (!(!m_disposed)) { std::cerr << "assert failed. cond=\""
<< "!m_disposed" << "\", "; do { std::cerr <<
"file=" << "../src/core/model/object.cc" << ", line="
<< 255 << std::endl; ::ns3::FatalImpl::FlushStreams
(); if (true) std::terminate (); } while (false); } } while (
false)
;
256 NS_ASSERT (!o->m_disposed)do { if (!(!o->m_disposed)) { std::cerr << "assert failed. cond=\""
<< "!o->m_disposed" << "\", "; do { std::cerr
<< "file=" << "../src/core/model/object.cc" <<
", line=" << 256 << std::endl; ::ns3::FatalImpl::
FlushStreams (); if (true) std::terminate (); } while (false)
; } } while (false)
;
257 NS_ASSERT (CheckLoose ())do { if (!(CheckLoose ())) { std::cerr << "assert failed. cond=\""
<< "CheckLoose ()" << "\", "; do { std::cerr <<
"file=" << "../src/core/model/object.cc" << ", line="
<< 257 << std::endl; ::ns3::FatalImpl::FlushStreams
(); if (true) std::terminate (); } while (false); } } while (
false)
;
258 NS_ASSERT (o->CheckLoose ())do { if (!(o->CheckLoose ())) { std::cerr << "assert failed. cond=\""
<< "o->CheckLoose ()" << "\", "; do { std::cerr
<< "file=" << "../src/core/model/object.cc" <<
", line=" << 258 << std::endl; ::ns3::FatalImpl::
FlushStreams (); if (true) std::terminate (); } while (false)
; } } while (false)
;
259
260 Object *other = PeekPointer (o);
261 // first create the new aggregate buffer.
262 uint32_t total = m_aggregates->n + other->m_aggregates->n;
263 struct Aggregates *aggregates =
264 (struct Aggregates *)std::malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
265 aggregates->n = total;
266
267 // copy our buffer to the new buffer
268 std::memcpy (&aggregates->buffer[0],
269 &m_aggregates->buffer[0],
270 m_aggregates->n*sizeof(Object*));
271
272 // append the other buffer into the new buffer too
273 for (uint32_t i = 0; i < other->m_aggregates->n; i++)
274 {
275 aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
276 const TypeId typeId = other->m_aggregates->buffer[i]->GetInstanceTypeId ();
277 if (DoGetObject (typeId))
278 {
279 NS_FATAL_ERROR ("Object::AggregateObject(): "do { std::cerr << "msg=\"" << "Object::AggregateObject(): "
"Multiple aggregation of objects of type " << other->
GetInstanceTypeId () << " on objects of type " <<
typeId << "\", "; do { std::cerr << "file=" <<
"../src/core/model/object.cc" << ", line=" << 282
<< std::endl; ::ns3::FatalImpl::FlushStreams (); if (true
) std::terminate (); } while (false); } while (false)
280 "Multiple aggregation of objects of type " <<do { std::cerr << "msg=\"" << "Object::AggregateObject(): "
"Multiple aggregation of objects of type " << other->
GetInstanceTypeId () << " on objects of type " <<
typeId << "\", "; do { std::cerr << "file=" <<
"../src/core/model/object.cc" << ", line=" << 282
<< std::endl; ::ns3::FatalImpl::FlushStreams (); if (true
) std::terminate (); } while (false); } while (false)
281 other->GetInstanceTypeId () <<do { std::cerr << "msg=\"" << "Object::AggregateObject(): "
"Multiple aggregation of objects of type " << other->
GetInstanceTypeId () << " on objects of type " <<
typeId << "\", "; do { std::cerr << "file=" <<
"../src/core/model/object.cc" << ", line=" << 282
<< std::endl; ::ns3::FatalImpl::FlushStreams (); if (true
) std::terminate (); } while (false); } while (false)
282 " on objects of type " << typeId)do { std::cerr << "msg=\"" << "Object::AggregateObject(): "
"Multiple aggregation of objects of type " << other->
GetInstanceTypeId () << " on objects of type " <<
typeId << "\", "; do { std::cerr << "file=" <<
"../src/core/model/object.cc" << ", line=" << 282
<< std::endl; ::ns3::FatalImpl::FlushStreams (); if (true
) std::terminate (); } while (false); } while (false)
;
283 }
284 UpdateSortedArray (aggregates, m_aggregates->n + i);
285 }
286
287 // keep track of the old aggregate buffers for the iteration
288 // of NotifyNewAggregates
289 struct Aggregates *a = m_aggregates;
290 struct Aggregates *b = other->m_aggregates;
291
292 // Then, assign the new aggregation buffer to every object
293 uint32_t n = aggregates->n;
294 for (uint32_t i = 0; i < n; i++)
295 {
296 Object *current = aggregates->buffer[i];
297 current->m_aggregates = aggregates;
298 }
299
300 // Finally, call NotifyNewAggregate on all the objects aggregates together.
301 // We purposedly use the old aggregate buffers to iterate over the objects
302 // because this allows us to assume that they will not change from under
303 // our feet, even if our users call AggregateObject from within their
304 // NotifyNewAggregate method.
305 for (uint32_t i = 0; i < a->n; i++)
306 {
307 Object *current = a->buffer[i];
308 current->NotifyNewAggregate ();
309 }
310 for (uint32_t i = 0; i < b->n; i++)
311 {
312 Object *current = b->buffer[i];
313 current->NotifyNewAggregate ();
314 }
315
316 // Now that we are done with them, we can free our old aggregate buffers
317 std::free (a);
318 std::free (b);
319}
320/**
321 * This function must be implemented in the stack that needs to notify
322 * other stacks connected to the node of their presence in the node.
323 */
324void
325Object::NotifyNewAggregate ()
326{
327 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
328}
329
330Object::AggregateIterator
331Object::GetAggregateIterator (void) const
332{
333 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
334 return AggregateIterator (this);
335}
336
337void
338Object::SetTypeId (TypeId tid)
339{
340 NS_LOG_FUNCTION (this << tid)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) <<
this << tid; std::clog << ")" << std::endl
; } } while (false)
;
341 NS_ASSERT (Check ())do { if (!(Check ())) { std::cerr << "assert failed. cond=\""
<< "Check ()" << "\", "; do { std::cerr <<
"file=" << "../src/core/model/object.cc" << ", line="
<< 341 << std::endl; ::ns3::FatalImpl::FlushStreams
(); if (true) std::terminate (); } while (false); } } while (
false)
;
342 m_tid = tid;
343}
344
345void
346Object::DoDispose (void)
347{
348 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
349 NS_ASSERT (!m_disposed)do { if (!(!m_disposed)) { std::cerr << "assert failed. cond=\""
<< "!m_disposed" << "\", "; do { std::cerr <<
"file=" << "../src/core/model/object.cc" << ", line="
<< 349 << std::endl; ::ns3::FatalImpl::FlushStreams
(); if (true) std::terminate (); } while (false); } } while (
false)
;
350}
351
352void
353Object::DoInitialize (void)
354{
355 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
356 NS_ASSERT (!m_initialized)do { if (!(!m_initialized)) { std::cerr << "assert failed. cond=\""
<< "!m_initialized" << "\", "; do { std::cerr <<
"file=" << "../src/core/model/object.cc" << ", line="
<< 356 << std::endl; ::ns3::FatalImpl::FlushStreams
(); if (true) std::terminate (); } while (false); } } while (
false)
;
357}
358
359bool
360Object::Check (void) const
361{
362 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
363 return (GetReferenceCount () > 0);
364}
365
366/* In some cases, when an event is scheduled against a subclass of
367 * Object, and if no one owns a reference directly to this object, the
368 * object is alive, has a refcount of zero and the method ran when the
369 * event expires runs against the raw pointer which means that we are
370 * manipulating an object with a refcount of zero. So, instead we
371 * check the aggregate reference count.
372 */
373bool
374Object::CheckLoose (void) const
375{
376 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
377 uint32_t refcount = 0;
378 uint32_t n = m_aggregates->n;
379 for (uint32_t i = 0; i < n; i++)
380 {
381 Object *current = m_aggregates->buffer[i];
382 /// \todo Shortcircuit this loop.
383 refcount += current->GetReferenceCount ();
384 }
385 return (refcount > 0);
386}
387void
388Object::DoDelete (void)
389{
390 // check if we really need to die
391 NS_LOG_FUNCTION (this)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) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
392 for (uint32_t i = 0; i < m_aggregates->n; i++)
1
Loop condition is true. Entering loop body
3
Loop condition is true. Entering loop body
5
Loop condition is false. Execution continues on line 404
393 {
394 Object *current = m_aggregates->buffer[i];
395 if (current->GetReferenceCount () > 0)
2
Taking false branch
4
Taking false branch
396 {
397 return;
398 }
399 }
400
401 // Now, we know that we are alone to use this aggregate so,
402 // we can dispose and delete everything safely.
403
404 uint32_t n = m_aggregates->n;
405 // Ensure we are disposed.
406 for (uint32_t i = 0; i < n; i++)
6
Loop condition is true. Entering loop body
8
Loop condition is true. Entering loop body
10
Loop condition is false. Execution continues on line 416
407 {
408 Object *current = m_aggregates->buffer[i];
409 if (!current->m_disposed)
7
Taking false branch
9
Taking false branch
410 {
411 current->DoDispose ();
412 }
413 }
414
415 // Now, actually delete all objects
416 struct Aggregates *aggregates = m_aggregates;
417 for (uint32_t i = 0; i < n; i++)
11
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
418 {
419 // There is a trick here: each time we call delete below,
420 // the deleted object is removed from the aggregate buffer
421 // in the destructor so, the index of the next element to
422 // lookup is always zero
423 Object *current = aggregates->buffer[0];
424 delete current;
12
Memory is released
14
Attempt to delete released memory
425 }
426}
427} // namespace ns3
428