/* * Copyright (c) 1994 by Xerox Corporation. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice.
*/
# ifndef GC_API_PRIV # define GC_API_PRIV GC_API # endif extern"C" {
GC_API_PRIV void GC_printf(constchar * format, ...); /* Use GC private output to reach the same log file. */ /* Don't include gc_priv.h, since that may include Windows system */ /* header files that don't take kindly to this context. */
}
#define my_assert( e ) \ if (! (e)) { \
GC_printf( "Assertion failure in " __FILE__ ", line %d: "#e"\n", \
__LINE__ ); \ exit( 1 ); }
#ifdefined(__powerpc64__) && !defined(__clang__) && GC_GNUC_PREREQ(10, 0) /* Suppress "layout of aggregates ... has changed" GCC note. */ # define A_I_TYPE short #else # define A_I_TYPE int #endif
class A {public: /* An uncollectible class. */
GC_ATTR_EXPLICIT A( int iArg ): i((A_I_TYPE)iArg) {} void Test( int iArg ) {
my_assert( i == iArg );} virtual ~A() {}
A_I_TYPE i; };
class B: public GC_NS_QUALIFY(gc), public A { public: /* A collectible class. */
GC_ATTR_EXPLICIT B( int j ): A( j ) {} virtual ~B() {
my_assert( deleting );} staticvoid Deleting( int on ) {
deleting = on;} staticint deleting;};
int B::deleting = 0;
#define C_INIT_LEFT_RIGHT(arg_l, arg_r) \
{ \
C *l = new C(arg_l); \
C *r = new C(arg_r); \
left = l; \
right = r; \ if (GC_is_heap_ptr(this)) { \
GC_END_STUBBORN_CHANGE(this); \
GC_reachable_here(l); \
GC_reachable_here(r); \
} \
}
class C: public GC_NS_QUALIFY(gc_cleanup), public A { public: /* A collectible class with cleanup and virtual multiple inheritance. */
// The class uses dynamic memory/resource allocation, so provide both // a copy constructor and an assignment operator to workaround a cppcheck // warning.
C(const C& c) : A(c.i), level(c.level), left(0), right(0) { if (level > 0)
C_INIT_LEFT_RIGHT(*c.left, *c.right);
}
C& operator=(const C& c) { if (this != &c) { delete left; delete right;
i = c.i;
level = c.level;
left = 0;
right = 0; if (level > 0)
C_INIT_LEFT_RIGHT(*c.left, *c.right);
} return *this;
}
GC_ATTR_EXPLICIT C( int levelArg ): A( levelArg ), level( levelArg ) {
nAllocated++; if (level > 0) {
C_INIT_LEFT_RIGHT(level - 1, level - 1);
} else {
left = right = 0;}}
~C() {
this->A::Test( level );
nFreed++;
my_assert( level == 0 ?
left == 0 && right == 0 :
level == left->level + 1 && level == right->level + 1 );
left = right = 0;
level = -123456;} staticvoid Test() { if (GC_is_incremental_mode() && nFreed < (nAllocated / 5) * 4) { // An explicit GC might be needed to reach the expected number // of the finalized objects.
GC_gcollect();
}
my_assert(nFreed <= nAllocated); # ifndef GC_NO_FINALIZATION
my_assert(nFreed >= (nAllocated / 5) * 4 || GC_get_find_leak()); # endif
}
staticint nFreed; staticint nAllocated; int level;
C* left;
C* right;};
int C::nFreed = 0; int C::nAllocated = 0;
class D: public GC_NS_QUALIFY(gc) { public: /* A collectible class with a static member function to be used as
an explicit clean-up function supplied to ::new. */
# ifdefined(CPPCHECK)
GC_noop1((GC_word)&WinMain); # endif if (cmd != 0) for (argc = 1; argc < (int)(sizeof(argv) / sizeof(argv[0])); argc++) { // Parse the command-line string. Non-reentrant strtok() is not used // to avoid complains of static analysis tools. (And, strtok_r() is // not available on some platforms.) The code is equivalent to: // if (!(argv[argc] = strtok(argc == 1 ? cmd : 0, " \t"))) break; if (NULL == cmd) {
argv[argc] = NULL; break;
} for (; *cmd != '\0'; cmd++) { if (*cmd != ' ' && *cmd != '\t') break;
} if ('\0' == *cmd) {
argv[argc] = NULL; break;
}
argv[argc] = cmd; while (*(++cmd) != '\0') { if (*cmd == ' ' || *cmd == '\t') break;
} if (*cmd != '\0') {
*(cmd++) = '\0';
} else {
cmd = NULL;
}
} #elifdefined(MACOS) int main() { char* argv_[] = {"test_cpp", "10"}; // MacOS doesn't have a command line
argv = argv_;
argc = sizeof(argv_)/sizeof(argv_[0]); #else int main( int argc, char* argv[] ) { #endif
GC_set_all_interior_pointers(1); /* needed due to C++ multiple inheritance used */
# ifdef TEST_MANUAL_VDB
GC_set_manual_vdb_allowed(1); # endif
GC_INIT(); # ifndef NO_INCREMENTAL
GC_enable_incremental(); # endif if (GC_get_find_leak())
GC_printf("This test program is not designed for leak detection mode\n");
int i, iters, n; int *x = gc_allocator<int>().allocate(1); int *xio;
xio = gc_allocator_ignore_off_page<int>().allocate(1);
GC_reachable_here(xio); int **xptr = traceable_allocator<int *>().allocate(1);
*x = 29; if (!xptr) {
fprintf(stderr, "Out of memory!\n"); exit(3);
}
GC_PTR_STORE_AND_DIRTY(xptr, x);
x = 0; if (argc != 2
|| (n = (int)COVERT_DATAFLOW(atoi(argv[1]))) <= 0) {
GC_printf("usage: test_cpp number-of-iterations\n" "Assuming 10 iters\n");
n = 10;
}
/* Allocate some uncollectible As and disguise their pointers. Later we'll check to see if the objects are still there. We're
checking to make sure these objects really are uncollectible. */
GC_word as[ 1000 ];
GC_word bs[ 1000 ]; for (i = 0; i < 1000; i++) {
as[ i ] = Disguise( new (GC_NS_QUALIFY(NoGC)) A(i) );
bs[ i ] = Disguise( new (GC_NS_QUALIFY(NoGC)) B(i) ); }
/* Allocate a fair number of finalizable Cs, Ds, and Fs.
Later we'll check to make sure they've gone away. */ for (i = 0; i < 1000; i++) {
C* c = new C( 2 );
C c1( 2 ); /* stack allocation should work too */
D* d;
F* f;
d = ::new (USE_GC, D::CleanUp, (void*)(GC_word)i) D( i );
GC_reachable_here(d);
f = new F;
F** fa = new F*[1];
fa[0] = f;
(void)fa; delete[] fa; if (0 == i % 10)
GC_CHECKED_DELETE(c);
}
/* Allocate a very large number of collectible As and Bs and drop the references to them immediately, forcing many
collections. */ for (i = 0; i < 1000000; i++) {
A* a;
a = new (USE_GC) A( i );
GC_reachable_here(a);
B* b;
b = new B( i );
(void)b;
b = new (USE_GC) B( i ); if (0 == i % 10) {
B::Deleting( 1 );
GC_CHECKED_DELETE(b);
B::Deleting( 0 );} # ifdefined(FINALIZE_ON_DEMAND) && !defined(GC_NO_FINALIZATION)
GC_invoke_finalizers(); # endif
}
/* Make sure the uncollectible As and Bs are still there. */ for (i = 0; i < 1000; i++) {
A* a = static_cast<A*>(Undisguise(as[i]));
B* b = static_cast<B*>(Undisguise(bs[i]));
a->Test( i ); # ifdefined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) // Workaround for ASan/MSan: the linker uses operator delete // implementation from libclang_rt instead of gc_cpp (thus // causing incompatible alloc/free).
GC_FREE(a); # else
GC_CHECKED_DELETE(a); # endif
b->Test( i );
B::Deleting( 1 );
GC_CHECKED_DELETE(b);
B::Deleting( 0 ); # ifdefined(FINALIZE_ON_DEMAND) && !defined(GC_NO_FINALIZATION)
GC_invoke_finalizers(); # endif
}
/* Make sure most of the finalizable Cs, Ds, and Fs have
gone away. */
C::Test();
D::Test();
F::Test();}
x = *xptr;
my_assert (29 == x[0]);
GC_printf( "The test appears to have succeeded.\n" ); return( 0 );
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.