⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obmalloc.c

📁 python s60 1.4.5版本的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (total < nbytes)
		/* overflow:  can't represent total as a size_t */
		return NULL;

	if (nbytes < original_nbytes) {
		/* shrinking:  mark old extra memory dead */
		memset(q + nbytes, DEADBYTE, original_nbytes - nbytes);
	}

	/* Resize and add decorations. */
	q = (uchar *)PyObject_Realloc(q - 2*SST, total);
	if (q == NULL)
		return NULL;

	write_size_t(q, nbytes);
	for (i = 0; i < SST; ++i)
		assert(q[SST + i] == FORBIDDENBYTE);
	q += 2*SST;
	tail = q + nbytes;
	memset(tail, FORBIDDENBYTE, SST);
	write_size_t(tail + SST, serialno);

	if (nbytes > original_nbytes) {
		/* growing:  mark new extra memory clean */
		memset(q + original_nbytes, CLEANBYTE,
			nbytes - original_nbytes);
	}

	return q;
}

/* Check the forbidden bytes on both ends of the memory allocated for p.
 * If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress,
 * and call Py_FatalError to kill the program.
 */
 void
_PyObject_DebugCheckAddress(const void *p)
{
	const uchar *q = (const uchar *)p;
	char *msg;
	size_t nbytes;
	const uchar *tail;
	int i;

	if (p == NULL) {
		msg = "didn't expect a NULL pointer";
		goto error;
	}

	/* Check the stuff at the start of p first:  if there's underwrite
	 * corruption, the number-of-bytes field may be nuts, and checking
	 * the tail could lead to a segfault then.
	 */
	for (i = SST; i >= 1; --i) {
		if (*(q-i) != FORBIDDENBYTE) {
			msg = "bad leading pad byte";
			goto error;
		}
	}

	nbytes = read_size_t(q - 2*SST);
	tail = q + nbytes;
	for (i = 0; i < SST; ++i) {
		if (tail[i] != FORBIDDENBYTE) {
			msg = "bad trailing pad byte";
			goto error;
		}
	}

	return;

error:
	_PyObject_DebugDumpAddress(p);
	Py_FatalError(msg);
}

/* Display info to stderr about the memory block at p. */
void
_PyObject_DebugDumpAddress(const void *p)
{
	const uchar *q = (const uchar *)p;
	const uchar *tail;
	size_t nbytes, serial;
	int i;
	int ok;

	fprintf(stderr, "Debug memory block at address p=%p:\n", p);
	if (p == NULL)
		return;

	nbytes = read_size_t(q - 2*SST);
	fprintf(stderr, "    %" PY_FORMAT_SIZE_T "u bytes originally "
	                "requested\n", nbytes);

	/* In case this is nuts, check the leading pad bytes first. */
	fprintf(stderr, "    The %d pad bytes at p-%d are ", SST, SST);
	ok = 1;
	for (i = 1; i <= SST; ++i) {
		if (*(q-i) != FORBIDDENBYTE) {
			ok = 0;
			break;
		}
	}
	if (ok)
		fputs("FORBIDDENBYTE, as expected.\n", stderr);
	else {
		fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
			FORBIDDENBYTE);
		for (i = SST; i >= 1; --i) {
			const uchar byte = *(q-i);
			fprintf(stderr, "        at p-%d: 0x%02x", i, byte);
			if (byte != FORBIDDENBYTE)
				fputs(" *** OUCH", stderr);
			fputc('\n', stderr);
		}

		fputs("    Because memory is corrupted at the start, the "
		      "count of bytes requested\n"
		      "       may be bogus, and checking the trailing pad "
		      "bytes may segfault.\n", stderr);
	}

	tail = q + nbytes;
	fprintf(stderr, "    The %d pad bytes at tail=%p are ", SST, tail);
	ok = 1;
	for (i = 0; i < SST; ++i) {
		if (tail[i] != FORBIDDENBYTE) {
			ok = 0;
			break;
		}
	}
	if (ok)
		fputs("FORBIDDENBYTE, as expected.\n", stderr);
	else {
		fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
			FORBIDDENBYTE);
		for (i = 0; i < SST; ++i) {
			const uchar byte = tail[i];
			fprintf(stderr, "        at tail+%d: 0x%02x",
				i, byte);
			if (byte != FORBIDDENBYTE)
				fputs(" *** OUCH", stderr);
			fputc('\n', stderr);
		}
	}

	serial = read_size_t(tail + SST);
	fprintf(stderr, "    The block was made by call #%" PY_FORMAT_SIZE_T
			"u to debug malloc/realloc.\n", serial);

	if (nbytes > 0) {
		i = 0;
		fputs("    Data at p:", stderr);
		/* print up to 8 bytes at the start */
		while (q < tail && i < 8) {
			fprintf(stderr, " %02x", *q);
			++i;
			++q;
		}
		/* and up to 8 at the end */
		if (q < tail) {
			if (tail - q > 8) {
				fputs(" ...", stderr);
				q = tail - 8;
			}
			while (q < tail) {
				fprintf(stderr, " %02x", *q);
				++q;
			}
		}
		fputc('\n', stderr);
	}
}

static size_t
printone(const char* msg, size_t value)
{
	int i, k;
	char buf[100];
	size_t origvalue = value;

	fputs(msg, stderr);
	for (i = (int)strlen(msg); i < 35; ++i)
		fputc(' ', stderr);
	fputc('=', stderr);

	/* Write the value with commas. */
	i = 22;
	buf[i--] = '\0';
	buf[i--] = '\n';
	k = 3;
	do {
		size_t nextvalue = value / 10;
		uint digit = (uint)(value - nextvalue * 10);
		value = nextvalue;
		buf[i--] = (char)(digit + '0');
		--k;
		if (k == 0 && value && i >= 0) {
			k = 3;
			buf[i--] = ',';
		}
	} while (value && i >= 0);

	while (i >= 0)
		buf[i--] = ' ';
	fputs(buf, stderr);

	return origvalue;
}

/* Print summary info to stderr about the state of pymalloc's structures.
 * In Py_DEBUG mode, also perform some expensive internal consistency
 * checks.
 */
void
_PyObject_DebugMallocStats(void)
{
	uint i;
	const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
	/* # of pools, allocated blocks, and free blocks per class index */
	size_t numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
	size_t numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
	size_t numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
	/* total # of allocated bytes in used and full pools */
	size_t allocated_bytes = 0;
	/* total # of available bytes in used pools */
	size_t available_bytes = 0;
	/* # of free pools + pools not yet carved out of current arena */
	uint numfreepools = 0;
	/* # of bytes for arena alignment padding */
	size_t arena_alignment = 0;
	/* # of bytes in used and full pools used for pool_headers */
	size_t pool_header_bytes = 0;
	/* # of bytes in used and full pools wasted due to quantization,
	 * i.e. the necessarily leftover space at the ends of used and
	 * full pools.
	 */
	size_t quantization = 0;
	/* # of arenas actually allocated. */
	size_t narenas = 0;
	/* running total -- should equal narenas * ARENA_SIZE */
	size_t total;
	char buf[128];

	fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
		SMALL_REQUEST_THRESHOLD, numclasses);

	for (i = 0; i < numclasses; ++i)
		numpools[i] = numblocks[i] = numfreeblocks[i] = 0;

	/* Because full pools aren't linked to from anything, it's easiest
	 * to march over all the arenas.  If we're lucky, most of the memory
	 * will be living in full pools -- would be a shame to miss them.
	 */
	for (i = 0; i < maxarenas; ++i) {
		uint poolsinarena;
		uint j;
		uptr base = arenas[i].address;

		/* Skip arenas which are not allocated. */
		if (arenas[i].address == (uptr)NULL)
			continue;
		narenas += 1;

		poolsinarena = arenas[i].ntotalpools;
		numfreepools += arenas[i].nfreepools;

		/* round up to pool alignment */
		if (base & (uptr)POOL_SIZE_MASK) {
			arena_alignment += POOL_SIZE;
			base &= ~(uptr)POOL_SIZE_MASK;
			base += POOL_SIZE;
		}

		/* visit every pool in the arena */
		assert(base <= (uptr) arenas[i].pool_address);
		for (j = 0;
			    base < (uptr) arenas[i].pool_address;
			    ++j, base += POOL_SIZE) {
			poolp p = (poolp)base;
			const uint sz = p->szidx;
			uint freeblocks;

			if (p->ref.count == 0) {
				/* currently unused */
				assert(pool_is_in_list(p, arenas[i].freepools));
				continue;
			}
			++numpools[sz];
			numblocks[sz] += p->ref.count;
			freeblocks = NUMBLOCKS(sz) - p->ref.count;
			numfreeblocks[sz] += freeblocks;
#ifdef Py_DEBUG
			if (freeblocks > 0)
				assert(pool_is_in_list(p, usedpools[sz + sz]));
#endif
		}
	}
	assert(narenas == narenas_currently_allocated);

	fputc('\n', stderr);
	fputs("class   size   num pools   blocks in use  avail blocks\n"
	      "-----   ----   ---------   -------------  ------------\n",
		stderr);

	for (i = 0; i < numclasses; ++i) {
		size_t p = numpools[i];
		size_t b = numblocks[i];
		size_t f = numfreeblocks[i];
		uint size = INDEX2SIZE(i);
		if (p == 0) {
			assert(b == 0 && f == 0);
			continue;
		}
		fprintf(stderr, "%5u %6u "
				"%11" PY_FORMAT_SIZE_T "u "
				"%15" PY_FORMAT_SIZE_T "u "
				"%13" PY_FORMAT_SIZE_T "u\n",
			i, size, p, b, f);
		allocated_bytes += b * size;
		available_bytes += f * size;
		pool_header_bytes += p * POOL_OVERHEAD;
		quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
	}
	fputc('\n', stderr);
	(void)printone("# times object malloc called", serialno);

	(void)printone("# arenas allocated total", ntimes_arena_allocated);
	(void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);
	(void)printone("# arenas highwater mark", narenas_highwater);
	(void)printone("# arenas allocated current", narenas);

	PyOS_snprintf(buf, sizeof(buf),
		"%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",
		narenas, ARENA_SIZE);
	(void)printone(buf, narenas * ARENA_SIZE);

	fputc('\n', stderr);

	total = printone("# bytes in allocated blocks", allocated_bytes);
	total += printone("# bytes in available blocks", available_bytes);

	PyOS_snprintf(buf, sizeof(buf),
		"%u unused pools * %d bytes", numfreepools, POOL_SIZE);
	total += printone(buf, (size_t)numfreepools * POOL_SIZE);

	total += printone("# bytes lost to pool headers", pool_header_bytes);
	total += printone("# bytes lost to quantization", quantization);
	total += printone("# bytes lost to arena alignment", arena_alignment);
	(void)printone("Total", total);
}

#endif	/* PYMALLOC_DEBUG */

#ifdef Py_USING_MEMORY_DEBUGGER
/* Make this function last so gcc won't inline it since the definition is
 * after the reference.
 */
int
Py_ADDRESS_IN_RANGE(void *P, poolp pool)
{
	return pool->arenaindex < maxarenas &&
	       (uptr)P - arenas[pool->arenaindex].address < (uptr)ARENA_SIZE &&
	       arenas[pool->arenaindex].address != 0;
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -