// http://blogs.msdn.com/b/vcblog/archive/2008/08/28/the-mallocator.aspx
template <typename T> class Mallocator;

template <> class Mallocator<void>
{
public:
    typedef void*        pointer;
    typedef const void*  const_pointer;
    // reference to void members are impossible.
    typedef void         value_type;

public:
    template <class U> struct rebind { typedef pool_allocator<U> other; };
};   

template <typename T>
class Mallocator
{
public:
 // The following will be the same for virtually all allocators.
 typedef T*        pointer;
 typedef const T*  const_pointer;
 typedef T&        reference;
 typedef const T&  const_reference;
 typedef T         value_type;
 typedef size_t    size_type;
 typedef ptrdiff_t difference_type;

public:
 // Default constructor, copy constructor, rebinding constructor, and destructor.
 // Empty for stateless allocators.
 Mallocator()
 {
 }

 ~Mallocator()
 {
 }

 Mallocator(const Mallocator&)
 {
 }

public:
 // The following must be the same for all allocators.
 template <typename U> struct rebind { typedef Mallocator<U> other; };
 template <typename U> Mallocator(const Mallocator<U>&) {}

 // Returns true if and only if storage allocated from *this
 // can be deallocated from other, and vice versa.
 // Always returns true for stateless allocators.
 bool operator==(const Mallocator& other) const
 {
  return true;
 }

 bool operator!=(const Mallocator& other) const
 {
  return !(*this == other);
 }

public:
 size_t max_size() const
 {
  // The following has been carefully written to be independent of
  // the definition of size_t and to avoid signed/unsigned warnings.
  return (static_cast<size_t>(0) - static_cast<size_t>(1)) / sizeof(T);
 }

 T* address(T& r) const
 {
  return &r;
 }

 const T* address(const T& s) const
 {
  return &s;
 }

 void construct(T * const p, const T& t) const
 {
  void * const pv = static_cast<void *>(p);
  new (pv) T(t);
 }

 void destroy(T * const p) const // Defined below.
 {
  p->~T();
 }

 // The following will be different for each allocator.
 T * allocate(const size_t n) const
 {
  // Mallocator prints a diagnostic message to demonstrate
  // what it's doing. Real allocators won't do this.
  //std::cout << "Allocating " << n << (n == 1 ? " object" : " objects") << " of size " << sizeof(T) << "." << std::endl;
  printf ("allocate n=%d size=%d \r\n", n, sizeof(T));

  // The return value of allocate(0) is unspecified.
  // Mallocator returns NULL in order to avoid depending
  // on malloc(0)'s implementation-defined behavior
  // (the implementation can define malloc(0) to return NULL,
  // in which case the bad_alloc check below would fire).
  // All allocators can return NULL in this case.
  if (n == 0)
  {
   return NULL;
  }

  // All allocators should contain an integer overflow check.
  // The Standardization Committee recommends that std::length_error
  // be thrown in the case of integer overflow.
  if (n > max_size())
  {
   throw std::length_error("Mallocator<T>::allocate() - Integer overflow.");
  }

  // Mallocator wraps malloc().
  void * const pv = malloc(n * sizeof(T));

  // Allocators should throw std::bad_alloc in the case of memory allocation failure.
  if (pv == NULL)
  {
   throw std::bad_alloc();
  }

  return static_cast<T *>(pv);
 }

 void deallocate(T * const p, const size_t n) const
 {
  // Mallocator prints a diagnostic message to demonstrate
  // what it's doing. Real allocators won't do this.
  std::cout << "Deallocating " << n << (n == 1 ? " object" : "objects") << " of size " << sizeof(T) << "." << std::endl;

  // Mallocator wraps free().
  free(p);
 }

 // The following will be the same for all allocators that ignore hints.
 template <typename U> T * allocate(const size_t n, const U * /* const hint */) const
 {
  return allocate(n);
 }

 // Allocators are not required to be assignable, so
 // all allocators should have a private unimplemented
 // assignment operator. Note that this will trigger the
 // off-by-default (enabled under /Wall) warning C4626
 // "assignment operator could not be generated because a
 // base class assignment operator is inaccessible" within
 // the STL headers, but that warning is useless.
private:
 Mallocator& operator=(const Mallocator&);
};

Posted by 셈말짓기 :

#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")
Posted by 셈말짓기 :

char* sitoa (char* a, int i)  
{  
 int   sign=0;  
 int   temp=0;  
 char  buf[16];  
 char* ptr;   

 ptr = buf;   

 /* zero then return */ 
 if( i )  
 {  
  /* make string in reverse form */ 
  if( i < 0 )
  {   
   i = ~i + 1;   
   sign++;
  }  
  while( i )
  {   
   *ptr++ = (i % 10) + '0';   
   i = i / 10;
  }  
  if(sign)  
  {
   *ptr++ = '-';  
  }
  *ptr = '\0';   

  /* copy reverse order */ 
  for( i=0; i < (int)strlen(buf); i++ )  
  {
   *a++ = buf[strlen(buf)-i-1];  
  }
 }      
 else
 {
  *a++ = '0';   
 }

 return a;  
}   

char* uitoa (char *a, unsigned int i)  
{  
 int   sign=0;  
 int   temp=0;  
 char  buf[16];  
 char* ptr;   

 ptr = buf;   

 /* zero then return */ 
 if( i )  
 {  
  while( i )
  {   
   *ptr++ = (i % 10) + '0';   
   i = i / 10;
  }  
  *ptr = '\0';   

  /* copy reverse order */ 
  for( i=0; i < (int)strlen(buf); i++ )  
  {
   *a++ = buf[strlen(buf)-i-1];  
  }
 }      
 else
 {
  *a++ = '0';   
 }

 return a;  
}   

char* htoa( char *a, unsigned int x, int opt)  
{  
 int   i;  
 int   sign=0;  
 int   temp=0;  
 char  buf[16];  
 char* ptr;   

 ptr = buf;   

 /* zero then return */ 
 if( x )  
 {  
  /* make string in reverse form */ 
  while( x )  
  {
   *ptr++ = (x&0x0f)<10 ? (x&0x0f)+'0' : (x&0x0f)-10+opt; x>>= 4;
  }   

  *ptr = '\0';   

  /* copy reverse order */ 
  for( i=0; i < (int)strlen(buf); i++ )  
  {
   *a++ = buf[strlen(buf)-i-1];  
  }
 }  
 else
 {
  *a++ = '0';   
 }
 return a;  
}

char * ltoa (long val, char *buf, unsigned radix)
{
 char *p;  /* pointer to traverse string */
 char *firstdig;  /* pointer to first digit */
 char temp;       /* temp char */
 unsigned digval; /* value of digit */

 p = buf;

 if (radix == 10 && val < 0) {
  /* negative, so output '-' and negate */
  *p++ = '-';
  val = (unsigned long)(-(long)val);
 }

 firstdig = p;    /* save pointer to first digit */

 do {
  digval = (unsigned) (val % radix);
  val /= radix;       /* get next digit */

  /* convert to ascii and store */
  if (digval > 9)
   *p++ = (char) (digval - 10 + 'a');  /* a letter */
  else
   *p++ = (char) (digval + '0');       /* a digit */
 } while (val > 0);

 /* We now have the digit of the number in the buffer, but in reverse
 order.  Thus we reverse them now. */

 *p-- = '\\0';     /* terminate string; p points to last digit */

 do {
  temp = *p;
  *p = *firstdig;
  *firstdig = temp;   /* swap *p and *firstdig */
  --p;
  ++firstdig;  /* advance to next two digits */
 } while (firstdig < p); /* repeat until halfway */

 return buf;
}


char *ftoa(float f, int *status)
{
 typedef union
 {
  long  L;
  float F;
 } LF_t;

 long  mantissa, int_part, frac_part;
 short exp2;

 LF_t  x;
 char* p;
 

 static char outbuf[15];


 *status = 0;
 if (f == 0.0)
 {
  outbuf[0] = '0';
  outbuf[1] = '.';
  outbuf[2] = '0';
  outbuf[3] =  0;
  return outbuf;
 }
 x.F = f;

 exp2      = (unsigned char)(x.L >> 23) - 127;
 mantissa  = (x.L & 0xFFFFFF) | 0x800000;
 frac_part = 0;
 int_part  = 0;

 if (exp2 >= 31)
 {
  *status = _FTOA_TOO_LARGE;
  return 0;
 }
 else if (exp2 < -23)
 {
  *status = _FTOA_TOO_SMALL;
  return 0;
 }
 else if (exp2 >= 23)
 {
  int_part = mantissa << (exp2 - 23);
 }
 else if (exp2 >= 0)
 {
  int_part = mantissa >> (23 - exp2);
  frac_part = (mantissa << (exp2 + 1)) & 0xFFFFFF;
 }
 else /* if (exp2 < 0) */
 {
  frac_part = (mantissa & 0xFFFFFF) >> -(exp2 + 1);
 }
 p = outbuf;

 if (x.L < 0)
 {
  *p++ = '-';
 }
 if (int_part == 0)
 {
  *p++ = '0';
 }
 else
 {
  ltoa(p, int_part, 10);
  while (*p)
   p++;
 }
 *p++ = '.';

 if (frac_part == 0)
  *p++ = '0';
 else
 {
  char m, max;

  max = sizeof (outbuf) - (p - outbuf) - 1;
  if (max > 7)
  {
   max = 7;
  }

  /* print BCD */
  for (m = 0; m < max; m++)
  {
   /* frac_part *= 10; */
   frac_part = (frac_part << 3) + (frac_part << 1);

   *p++ = (frac_part >> 24) + '0';
   frac_part &= 0xFFFFFF;
  }
  /* delete ending zeroes */
  for (--p; p[0] == '0' && p[-1] != '.'; --p)
   ;
  ++p;
 }
 *p = 0;

 return outbuf;
}

Posted by 셈말짓기 :

// TestSprintF.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

int sprintf_with_args (char* buf, char* format, void** args)
{  
 char* start;  

 char  field_format[32];
 char* field;
 char* field_type;

 int   result;


 start = buf;

 while( *format )  
 {  
  if( *format != '%' )
  {  
   *buf++ = *format++;  
   continue;  
  }

  field      = field_format;
  field_type = 0;

  *field++ = *format++;
  while( *format && !field_type && field<field_format+32)
  {
   switch (*format)
   {
   case '%':
   case 'c'://int
   case 'C':
   case 'd':
   case 'i':
   case 'o':
   case 'u':
   case 'x':
   case 'X':
   case 'e':
   case 'E'://double
   case 'f':
   case 'g':
   case 'G':
   case 'a':
   case 'A':
   case 'n'://int*
   case 'p'://void*
   case 's'://char*
   case 'S'://wchar_t*
    field_type = format;
    break;
   }
   *field++ = *format++;
  }

  if (field_type)
  {
   *field = 0;
#pragma warning( push )
#pragma warning( disable: 4996 )
   switch (*field_type)
   {
   case '%':
    *buf++ = '%'; 
    break;

   case 'c'://int
   case 'C':
   case 'd':
   case 'i':
   case 'o':
   case 'u':
   case 'x':
   case 'X':
    result = sprintf (buf, field_format, *((int*)(*args)));
    if (result>0)
    {
     buf+=result;
    }
    else
    {
     return -1;
    }
    args++;
    break;
   case 'e':
   case 'E'://double
   case 'f':
   case 'g':
   case 'G':
   case 'a':
   case 'A':
    result = sprintf (buf, field_format, *((double*)(*args)));
    if (result>0)
    {
     buf+=result;
    }
    else
    {
     return -1;
    }
    args++;
    break;
   case 'n'://int*
   case 'p'://void*
   case 's'://char*
   case 'S'://wchar_t*
    result = sprintf (buf, field_format, *((int**)(*args)));
    if (result>0)
    {
     buf+=result;
    }
    else
    {
     return -1;
    }
    args++;
    break;
   }
  }
#pragma warning( pop )
 }
 *buf = '\0';   

 return (int)(buf-start); 

 return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
 char*  pFormatString = "문자열%%[%d][%d][%5d] [%s] [%x] [%e][%.03f]메%q세지 \r\n";
 char   szMessage[256];
 void*  pParameters[7];
 int    Parameters[32];
 char   param1 = 100;
 short  param2 = 101;
 int    param3 = 102;
 char*  param4 = "xxx";
 int    param5 = -1;
 double param6 = 0.1;
 double param7 = 0.5;

 Parameters[0] = (int)param1;
 Parameters[1] = (int)param2;
 Parameters[2] = (int)param3;
 Parameters[3] = (int)param4;
 Parameters[4] = (int)param5;
 memcpy (&Parameters[5], &param6, sizeof(double));
 memcpy (&Parameters[7], &param7, sizeof(double));

#if 0
 pParameters[0] = &Parameters[0];
 pParameters[1] = &Parameters[1];
 pParameters[2] = &Parameters[2];
 pParameters[3] = &Parameters[3];
 pParameters[4] = &Parameters[4];
 pParameters[5] = &Parameters[5];
 pParameters[6] = &Parameters[7];
#else
 pParameters[0] = &param1;
 pParameters[1] = &param2;
 pParameters[2] = &param3;
 pParameters[3] = &param4;
 pParameters[4] = &param5;
 pParameters[5] = &param6;
 pParameters[6] = &param7;
#endif

 sprintf_with_args (szMessage, pFormatString, pParameters);
 printf (szMessage);

 return 0;
}


 

Posted by 셈말짓기 :

#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  g_my_jump_buffer;

bool try_signal (int sig)
{
    int result;

    result = setjmp(my_jump_buffer, sig);
    printf ("setjmp(): resutl %d \r\n", result);
    if (sig==result)
        return true;
    return false;
}

void signal_handler (int sig)
{
    printf ("signal_handler(%d) \r\n", sig);
    longjmp (g_my_jump_buffer, sig);
}

int main (void)
{
    unsigned int* p = (unsigned int*)0xffffffff;

    signal (SIGBUS, signal_handler);

    while (1)
    {    
        if (try_signal (SIGBUS)==0)
        {
            printf ("no signal \r\n");
            *p = 0x00000001;
        }
        else
        {
            printf ("signal \r\n");
        }
    }
    return 0;
}

이런식으로 setjmp를 사용하면 프로그램이 망한다.
setjmp시 현재 스택 포인터를 저장하는 역할을 하기 때문에 위에 처럼 setjmp를 랩핑해서 함수를 호출하여 사용하면
1. 위에 main함수에서 try_signal()을 호출하고 
2. signal이 발생되어서 signal_handler()를 거쳐서
3. 다시 setjmp()함수 위치로 복귀하려 했을때 
   이전 try_signal()이 호출 되어서 저장했던 스택포인터는 
   이전 try_singal()가 main()함수로 복귀를 했으므로 저장했던 해당 스택포인터가 유효 하지 않다.
랩핑해서 사용하고 싶을땐 아래와 같이 inline함수로 구현하던가 매크로로 구현해야한다.

#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  g_my_jump_buffer;

inline bool try_signal (int sig)
{
    int result;

    result = setjmp(my_jump_buffer, sig);
    printf ("setjmp(): resutl %d \r\n", result);
    if (sig==result)
        return true;
    return false;
}

void signal_handler (int sig)
{
    printf ("signal_handler(%d) \r\n", sig);
    longjmp (g_my_jump_buffer, sig);
}

int main (void)
{
    unsigned int* p = (unsigned int*)0xffffffff;

    signal (SIGBUS, signal_handler);

    while (1)
    {    
        if (try_signal (SIGBUS)==0)
        {
            printf ("no signal \r\n");
            *p = 0x00000001;
        }
        else
        {
            printf ("signal \r\n");
        }
    }
    return 0;
}

Posted by 셈말짓기 :