Новые книги

Инсайдерское откровение о том, как один человек построил мировую корпорацию, способную противостоять таким гигантам как Walmart и Amazon.

Всего за десять лет Джек Ма, бывший преподаватель английского, основал и построил Alibaba Group, в которую сегодня входят: Alibaba.com, Alibaba Pictures, AliExpress.com, Taobao.com, Tmall.com, Alipay и другие.

Джек Ма – Рокфеллер XXI века, акции Alibaba в 2014 году побили рекорды, достигнув 25 млрд долларов.

Перед вами история компании и самого Джека, иконы частного предпринимательства и привратника миллионов потребителей от китайского Ханчжоу до тверского Торжка.
Эта книга поможет вам быстро создать свой бизнес. Независимо от того, есть ли у вас собственное дело или вы только собираетесь начать его, она даст вам надежный ренет ускорения.

Задумайтесь о следующем: что, если бы вы могли осуществить выведение своего продукта на рынок подобно Apple или крупной голливудской студии? Что. если бы ваши потенциальные покупатели считали бы дни до того момента, когда они смогут купить ваш продукт? Что, если бы вы смогли обеспечить себе такое прочное позиционирование на вашем рынке, которое почти бы полностью устранило для вас конкуренцию? И вы могли бы делать все это, независимо от того, каким бы скромным ни был ваш бизнес или ваш бюджет?

Теперь вопрос заключается в следующем – вы в самом деле собираетесь начать работать медленно и вскоре угаснуть? Или же вы готовы осуществить старт; который изменит будущее вашего бизнеса и вашу жизнь?

Права на издание получены по соглашению с Morgan James Publishing. Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.

Примеры.

Пример 11

/* Пакет для ловли наездов областей выделенной памяти
 * друг на друга,
 * а также просто повреждений динамически отведенной памяти.
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>      /* O_RDWR */
#include <sys/types.h>
#include <ctype.h>
#include <locale.h>
#define CHECKALL
/*
	----------------- <--------- ptr
	| red_zone      | головная "пограничная зона"
	----------------	| byte[0]       |
	|     ...       |
	| byte[size-1]  |
	| placeholder   |
	----------------- выровнено на границу RedZoneType
	| red_zone      | хвостовая "пограничная зона"
	----------------
Основные идеи состоят в следующем:
1) Перед и после области данных строится зона,
   заполненная заранее известным "узором".
   Если ее содержимое изменилось, испорчено    значит мы где-то разрушили нашу память.
2) Ведется таблица всех отведенных malloc()-ом сегментов памяти;
   для экономии места эта таблица вынесена в файл (но зато это
   очень медленно).
3) Мы не можем пользоваться библиотекой STDIO для обменов с файлом,
   потому что эта библиотека сама использует malloc() и буфера
   могут быть разрушены.
*/
typedef char *RedZoneType;      /* выравнивание на границу указателя */
/* Можно выравнивать на границу double:
typedef double RedZoneType;
 */
/* Сегмент, выделяемый в оперативной памяти */
typedef struct _allocFrame {
	RedZoneType red_zone;   /* головная "пограничная зона"            */
	RedZoneType stuff[1];   /* место для данных                       */
				/* хвостовая "пограничная зона" безымянна */
} AllocFrame;
const int RedZoneTypeSize = sizeof(RedZoneType);
/* Запись, помещаемая в таблицу всех выделенных malloc()ом
 * областей памяти.
 */
typedef struct _memFileRecord {
	AllocFrame *ptr;        /* адрес                                 */
	size_t size, adjsize;   /* размер выделенной области             */
				/* (0,0) - означает "сегмент освобожден" */
	int serial;
} MemFileRecord;
char red_table[] = {
	0x01, 0x03, 0x02, 0x04,
	0x11, 0x13, 0x12, 0x14,
	0x21, 0x23, 0x22, 0x24,
	0x31, 0x33, 0x32, 0x34
};
char free_table[] = {
	'F', 'r', 'e', 'e', 'p', 't', 'r', '\0',
	'F', 'r', 'e', 'e', 'p', 't', 'r', '\0'
};
/* Файл для хранения таблицы указателей */
static  int mem_fd = (-1);
#define PTABLE "PointerTable.bin"
#define NRECORDS 256
MemFileRecord memrecords[NRECORDS];
/* ============================================================= */
void  MEMputTableRecord(AllocFrame *newptr, AllocFrame *oldptr,
			size_t size, size_t adjsize);
void  MEMputTableRecordKilled(AllocFrame *ptr);
void  MEMerasePreviousRecords(AllocFrame *ptr);
int   MEMcheckRecord(MemFileRecord *rec);
int   MEMcheck_consistency(AllocFrame *ptr);
void  MEMmakeRedZones(char *cptr, size_t size, size_t adjsize);
void  MEMopenFd();
/* ============================================================= */
/* Этим следует пользоваться вместо стандартных функций          */
void *MEMmalloc (size_t size);
void *MEMrealloc(void *ptr, size_t size);
void *MEMcalloc (size_t n,  size_t size);
void  MEMfree   (void *ptr);
void  MEMcheckAll();  /* это можно вызывать в середине программы */
/* ============================================================= */
void MEMopenFd(){
	if(mem_fd < 0){
		close(creat(PTABLE, 0644));     /* создать файл */
		mem_fd = open(PTABLE, O_RDWR);  /* чтение+запись */
		unlink(PTABLE);                 /* только для M_UNIX */
		atexit(MEMcheckAll);
		setlocale(LC_ALL, "");
	}
}
/* Поместить запись в таблицу всех указателей на
 * выделенные области памяти.
 */
void MEMputTableRecord(AllocFrame *newptr, /* для записи */
		       AllocFrame *oldptr, /* для стирания */
		       size_t size,        /* размер данных */
		       size_t adjsize      /* размер всей записи с зонами */
){
	MemFileRecord memrecord;
	static int serial = 0;
	memrecord.ptr     = newptr;
	memrecord.size    = size;
	memrecord.adjsize = adjsize;
	memrecord.serial  = serial++;
	MEMopenFd();
#ifdef CHECKALL
	/* стереть прежние записи про этот адрес */
	MEMerasePreviousRecords(oldptr);
#endif
	lseek(mem_fd, 0L, SEEK_END);                    /* в конец */
	write(mem_fd, &memrecord, sizeof memrecord);    /* добавить */
}
/* Сделать запись об уничтожении области памяти */
void  MEMputTableRecordKilled(AllocFrame *ptr){
	/* Пометить как size=0, adjsize=0 */
	MEMputTableRecord(ptr, ptr, 0, 0);
}
/* Коды ответа функции проверки */
#define OK      0       /* все хорошо                 */
#define DAMAGED 1       /* повреждена "погранзона"    */
#define FREED   2       /* эта память уже освобождена */
#define NOTHERE (-1)    /* нет в таблице              */
/* Проверить сохранность "пограничных зон" */
int MEMcheckRecord(MemFileRecord *rec){
	int code = OK;
	char *cptr;
	register i;
	AllocFrame *ptr        = rec->ptr;
	size_t size            = rec->size;
	size_t adjsize         = rec->adjsize;
	if(size == 0 && adjsize == 0){
		printf("%p [%p] -- сегмент уже освобожден, "
		       "record=#%d.\n",
			&ptr->stuff[0], ptr,
			rec->serial
		);
		return FREED;
	}
	cptr    = (char *) ptr;
	for(i=0; i < adjsize; i++){
	    if(i <  RedZoneTypeSize || i >= RedZoneTypeSize + size ){
		/* головная погранзона ИЛИ хвостовая погранзона */
		if( cptr[i] != red_table[ i % RedZoneTypeSize ] ){
		   printf("%p [%p] -- испорчен байт %4d [%4d]"
			  "= 0x%02X '%c' record=#%d size=%lu.\n",
			   &ptr->stuff[0], ptr,
			   i - RedZoneTypeSize, i,
			   cptr[i] & 0xFF,
			   isprint(cptr[i] & 0xFF) ? cptr[i] & 0xFF : '?',
			   rec->serial, size
		   );
		   code = DAMAGED;
		}
	    }
	}
	for(i=0; i < RedZoneTypeSize; i++)
		if(cptr[i] == free_table[i]){
			printf("%p -- уже освобождено?\n", ptr);
			code = FREED;
		}
	if(code != OK) putchar('\n');
	return code;
}
/* Проверить сохранность памяти по указателю ptr. */
int MEMcheck_consistency(AllocFrame *ptr){
	MemFileRecord mr_found;
	int nrecords, i, found = 0;
	size_t size;
	MEMopenFd();
	/* Ищем запись в таблице указателей */
	lseek(mem_fd, 0L, SEEK_SET);    /* перемотать в начало */
	for(;;){
		size = read(mem_fd, memrecords, sizeof memrecords);
		nrecords = size / sizeof(memrecords[0]);
		if(nrecords <= 0) break;
		for(i=0; i < nrecords; i++)
			if(memrecords[i].ptr == ptr){
			/* Мы ищем последнюю запись про память
			 * с таким адресом, поэтому
			 * вынуждены прочитать ВЕСЬ файл.
			 */
				mr_found = memrecords[i];
				found++;
			}
	}
	if(found) {
		return MEMcheckRecord(&mr_found);
	} else {
		printf("%p -- запись в таблице отсутствует.\n", ptr);
		return NOTHERE;
	}
}
/* Уничтожить все прежние записи про ptr, прописывая их adjsize=0 */
void MEMerasePreviousRecords(AllocFrame *ptr){
	int nrecords, i, found;
	size_t size;
	MEMopenFd();
	lseek(mem_fd, 0L, SEEK_SET);    /* перемотать в начало */
	for(;;){
		found = 0;
		size = read(mem_fd, memrecords, sizeof memrecords);
		nrecords = size / sizeof(memrecords[0]);
		if(nrecords <= 0) break;
		for(i=0; i < nrecords; i++)
			if(memrecords[i].ptr == ptr){
				memrecords[i].adjsize = 0;
				/* memrecords[i].size = 0; */
				found++;
			}
		if(found){
			lseek(mem_fd, -size, SEEK_CUR);    /* шаг назад */
			write(mem_fd, memrecords, size);   /* перезаписать */
		}
	}
}
void MEMcheckAll(){
#ifdef CHECKALL
	int nrecords, i;
	size_t size;
	printf("Проверка всех указателей -------------\n");
	MEMopenFd();
	lseek(mem_fd, 0L, SEEK_SET);    /* перемотать в начало */
	for(;;){
		size = read(mem_fd, memrecords, sizeof memrecords);
		nrecords = size / sizeof(memrecords[0]);
		if(nrecords <= 0) break;
		for(i=0; i < nrecords; i++)
			if(memrecords[i].adjsize != 0)
				MEMcheckRecord(&memrecords[i]);
	}
	printf("Проверка всех указателей завершена ---\n");
#endif
}
/* ============================================================= */
/* Заполнение пограничных зон образцом - "следовой дорожкой" */
void MEMmakeRedZones(char *cptr, size_t size, size_t adjsize){
	register i;
	for(i=0; i < adjsize; i++){
		if(i <  RedZoneTypeSize || i >= RedZoneTypeSize + size ){
		   /* головная погранзона ИЛИ
		    * хвостовая погранзона + дополнение
		    * до целого числа RedZoneType-ов
		    */
			cptr[i] = red_table[ i % RedZoneTypeSize ];
		}
	}
}
/* ============================================================= */
/* Функция выделения памяти */
void *MEMmalloc(size_t size){
	AllocFrame *retptr;
	int fullRedZoneTypes =
		(size + RedZoneTypeSize - 1) / RedZoneTypeSize;
	size_t adjustedSize =
		sizeof(retptr->red_zone) * 2 + /* две погранзоны */
		fullRedZoneTypes * RedZoneTypeSize;
	retptr  = (AllocFrame *) malloc(adjustedSize);
	if(retptr == NULL) return NULL;
	MEMmakeRedZones ((char *) retptr, size, adjustedSize);
	MEMputTableRecord(retptr, retptr, size, adjustedSize);
	return &retptr->stuff[0];
	/* вернуть указатель на зону данных */
}
void *MEMrealloc(void *ptr, size_t size){
	AllocFrame *retptr;
	char *cptr = (char *)ptr - RedZoneTypeSize;  /* прежний AllocFrame */
	AllocFrame *oldptr = (AllocFrame *) cptr;
	int fullRedZoneTypes =
		(size + RedZoneTypeSize - 1) / RedZoneTypeSize;
	size_t adjustedSize =
		sizeof(retptr->red_zone) * 2 +
		fullRedZoneTypes * RedZoneTypeSize;
	/* Проверить сохранность того, что мы сейчас будем realloc-ить */
	MEMcheck_consistency(oldptr);
	retptr  = (AllocFrame *) realloc((void *)oldptr, adjustedSize);
	if(retptr == NULL) return NULL;
	MEMmakeRedZones ((char *) retptr, size, adjustedSize);
	MEMputTableRecord(retptr, oldptr, size, adjustedSize);
	return &retptr->stuff[0];
}
void *MEMcalloc(size_t n, size_t size){
	size_t newsize = n * size;
	void *ptr = MEMmalloc(newsize);
	memset(ptr, '\0', newsize);
	return ptr;
}
/* Очистка отведенной памяти.
 * ptr - это указатель не на AllocFrame,
 * а на данные - то есть на stuff[0].
 */
void MEMfree(void *ptr){
	char *cptr = (char *)ptr - RedZoneTypeSize;
	int i, code;
	code = MEMcheck_consistency((AllocFrame *) cptr);
	for(i=0; i < RedZoneTypeSize; i++)
		cptr[i] = free_table[i];
	if(code != FREED) free((void *) cptr);
	MEMputTableRecordKilled((AllocFrame *) cptr);
}
/* ============================================================= */
/* Тестовый пример                                               */
/* ============================================================= */
#define MAXPTRS 512
char *testtable[MAXPTRS];
/* Сгенерировать строку случайной длины со случайным содержимым */
char *wildstring(int c){
#define N 1024
	char teststring[N + 1];
	int len, i;
	char *ptr;
	len = rand() % N;
	for(i=0; i < len; i++)
		teststring[i] = c;
	teststring[len] = '\0';
	ptr = (char *) MEMmalloc(len + 1);
	if(ptr){
		strcpy(ptr, teststring);
	} else printf("NULL wildstring()\n");
	return ptr;
}
int main(int ac, char *av[]){
	int ilen, len, n, i;
	srand(time(NULL));
	for(n=0; n < MAXPTRS; n++)
		testtable[n] = wildstring('A');
#define DAMAGE (MAXPTRS/3*2-1)
#ifdef DAMAGE
	/* Навести порчу */
	len = strlen(testtable[DAMAGE]);
	testtable[DAMAGE][len+1] = 'x';
	testtable[DAMAGE][-2]    = 'y';
	printf("ptr=%p len=%d\n", testtable[DAMAGE], len);
#endif
	for(n=0; n < MAXPTRS/2; n++){
		char *p = wildstring('B');
		int length = strlen(p);
		char *ptr;
		i = rand() % MAXPTRS;
		/* Не забыть присвоить возвращенное realloc() значение
		 * обратно в testtable[i] !!!
		 */
		testtable[i] = ptr =
			(char *) MEMrealloc(testtable[i], length + 1);
		if(ptr == NULL) printf("Не могу сделать realloc()\n");
		else            strcpy(ptr, p);
#ifdef DAMAGE
		/* Порча */
		if(n == MAXPTRS/3){
			ptr[length+2] = 'z';
		}
#endif
		MEMfree(p);
	}
	for(n=0; n < MAXPTRS; n++){
		if(testtable[n]) MEMfree(testtable[n]);
	}
#ifdef DAMAGE
	MEMfree(testtable[DAMAGE]);
#endif
	return 0;
}

© Copyright А. Богатырев, 1992-95
Си в UNIX

Назад | Содержание | Вперед