수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1693968
  • Today | 319
  • Yesterday | 588

Programming/C++2007/07/27 16:43

C++ In Theory: The Singleton Pattern

출처 : http://www.devarticles.com/c/a/cplusplu ··· art-i%2F

C++ In Theory: The Singleton Pattern, Part I
(Page 1 of 5 )

Have you ever wondered how to implement a class with simple logging functionality? J. Nakamura explains how to do it in a way that makes use of the Singleton pattern.

There is a great book called “Design Patterns” [Gamma] that encapsulates knowledge trapped inside the heads of experienced programmers, presenting it in understandable and useable chunks. Solutions to a lot of design problems often turn out to be the same, even when programmers discover them independently. Instead of providing these solutions to you in code format, the “Design Patterns” book presents the thoughts and reasoning behind the solutions along with example code.

Design Patterns are a great way to get a head start on solving that problem you have encountered or might yet have to encounter. In this article we are going to implement a class with simple logging functionality that will make use of the Singleton pattern. My intention is not to present you with a class that will end all your logging woes, but rather to use it to demonstrate why you need this pattern.

Writing to a log is an action where it makes sense to have only one single log object active at any time you want to register data with it. It doesn’t matter which part of your application is writing to the log, as long as all parts are using the same log.

In an older programming language such as C you might choose global variables and global functions to implement such facilities, but as a project grows larger the risk of adding subtle bugs grows as well. These global variables and global functions all end up in the global namespace, and the introduction of a foreign library (or any new code for that matter) might cause naming collisions (meaning there are multiple variables/functions sharing the same name/identifier). Such collisions can only be resolved by changing the names of your own global variables and/or functions; these changes are bug prone and quite a chore in large projects with a lot of source files.

The benefit of the Singleton pattern (which can be implemented in C++) is that it prevents you from filling up the global namespace. You can keep the variables and functions locked up inside a class and restrict access to it by implementing a single point of access, which prevents you from creating multiple instances of the class. Other great features of the C++ language such as polymorphism (changing the behavior of a class through virtual functions) remain available to you as well.


C++ In Theory: The Singleton Pattern, Part I - A Logging Class
(Page 2 of 5 )

Here is a simple class that collects strings and can write them to a file. This class will represent the log we aim to implement in this article.

// log.h
#ifndef __LOG_H
#define __LOG_H

#include <list>
#include <string>

class Log {
public:
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  std::list<std::string> m_data;
};
#endif // __LOG_H
// eof

// log.cpp
#include <fstream>
using namespace std;

#include “log.h”

void Log::Write(char const *logline)
{
m_data.push_back(logline);
}

bool Log::SaveTo(char const *filename)
{
  ofstream file(filename, ios::out);
  list<string>::iterator it;
  list<string>::iterator lastIt=m_data.end();
  for (it=m_data.begin(); it!=lastIt; ++it)
   file << *it << endl;
  file.close();
}

// eof

We are going to alter the behavior of this class to ensure that only one instantiation of it can be created during the lifetime of an application using it. This will cause all strings provided in calls to Log::Write, to end up in a single list (Log::m_data) which can be written to a single file when Log::Write is called.

C++ In Theory: The Singleton Pattern, Part I - Statics are not Singletons
(Page 3 of 5 )

Forcing the existence of only one instance of the Log class seems easily implemented when we use only static variables and functions:

class Log {
public:
  static void Write(char const *logline);
  static bool SaveTo(char const *filename);
private:
  static std::list<std::string> m_data;
};

In log.cpp we need to add

std::list<std::string> Log::m_data;

Though it looks like it fulfills our goal, there are some downsides to these kinds of singleton implementations. First of all, the construction and destruction of static member variables are difficult to localize. They are instantiated in any sequence by grace of the compiler, outside any constructors. This can cause tremendous problems when singletons depend on the right construction/destruction sequence

Second, it is not possible to implement polymorphic behavior this way because static functions cannot be virtual. This means that a singleton implemented with static variables/functions cannot be accessed through its baseclass. For example, when our application runs standalone on a machine we probably want to save the log to a file, but when it is part of a distributed application we might want to save the log to a logging server. Instead of bundling all functionality into one big fat "does-everything" class, we split the behavior up in to separate classes, all implementing the interface of the abstract baseclass:

// LogBase.h
class LogBase {
public:
  virtual ~LogBase() {}
  virtual void Write(char const *logline)=0;
  virtual bool SaveTo(char const *filename)=0;
};

The destructor of our baseclass has to be declared virtual, otherwise the destructor of a derived class will not be called when it is destroyed through the baseclass.

// LogFile.h
class LogFile : public LogBase {
public:
  virtual ~LogFile();
  virtual void Write(char const *logline);
  virtual void SaveTo(char const *filename);
private:
  std::list<std::string> m_data;
};

// LogNetwork.h
class LogNetwork : public LogNetwork {
public:
  virtual ~LogNetwork();
  virtual void Write(char const *logline);
  virtual void SaveTo(char const *filename);
  virtual void SetServer(TCPConnection const &server);
private:
  TCPConnection m_logServer;
  std::list<std::string> m_data;
};

It is good to give each class its own responsibility, and to choose which Log class you will use during runtime. This prevents us from having to instantiate code we will not need:

int main(int argc, char *argv[])
{
  LogBase *myLog = NULL;
 
if (argc == 1)
  {
   ShowUsage();
   return –1;
}

  if (strcmp(argv[1], ”-StandAlone”)==0)
   myLog = reinterpret_cast<LogBase*>(new LogFile);
  else if (strcmp(argv[1], “-Networked”)==0)
{
  TCPConnection fictServer(“127.0.0.1:31280”);
  LogNetwork *logPtr = new LogNetwork;
  logPtr->SetServer(fictServer);
   myLog = reinterpret_cast<LogBase*>(logPtr); 
  }
  else
  {
   ShowUsage();
   return –1;
  }
  /* more code here */
  // logging example
  myLog->Write(“test line going to either a file or network log.”);
}

This is of course a fictional example, but I hope you get the idea of what polymorphic behavior can mean for your application. In the example above, application code can log through the LogBase class, but depending on the arguments given during start-up, the logs will either be written to file or to a network server.

C++ In Theory: The Singleton Pattern, Part I - The Gamma Singleton
(Page 4 of 5 )

It is clear that singletons are not very flexible when we have to rely on static variables and functions. But I have digressed a little, so let's have a look at how the Log class would be implemented as a singleton in "Design Patterns" [Gamma].

class Log {

public:
  static Log* Instance() {
   if (!m_pInstance)
     m_pInstance = new Log;
   return m_pInstance;
}
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  Log();        // ctor is hidden
  Log(Log const&);    // copy ctor is hidden

  static Log* m_pInstance;
  static std::list<std::string> m_data;
};

// in log.cpp we have to add
Log* Log::m_pInstance = NULL;

The constructor and copy constructor are hidden because they are made private, so no user has access to them except for the class itself. The only way to instantiate a Log is by calling Instance() which checks whether or not this class has already been instantiated. This seems like the perfect way to restrict access to our class, and we are sure that only one is ever created during the lifetime of our application!

“Seems?” I hear you think. If you look closely, you will notice that m_pInstance is never destructed. Depending on the definition you use for memory leakage, this class is actually leaking memory.

Some consider a memory leak to be an accumulation of data, of which you lose the references (and thus the ability to free them) during runtime. In this case m_pInstance is holding on to the memory right up to the end of the application, so does not have to be considered a memory leak. Since most operating systems free the memory a process has been using when it terminates, m_pInstance can be considered not to be leaking.

You should not depend on the operating system to clean up the memory you have allocated, especially not when your code has to be platform independent. There is at least one OS out there that doesn’t free the memory left allocated by a terminated process (I don't remember which one…most probably it is the OS/400) and if your singleton opened a file, socket or other system resources, these may remain locked after the process has closed and you will have created a resource leak.

Maybe we should have coded our Log singleton this way:

class Log {
public:
  static Log* Instance() {
   return &m_pInstance;
}
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  Log();        // ctor is hidden
  Log(Log const&);    // copy ctor is hidden

  static Log m_pInstance;
  static std::list<std::string> m_data;
};

// in log.cpp we have to add
Log Log::m_pInstance;

This solution loses an important benefit that our previous singleton did have: dynamic initialization. It is useful for your application to only create the singleton when it is needed/called upon. With our polymorphic example, every class would be instantiated and we would have to instantiate all forms of logging (even when this might not be possible!), while only using one of them!

Static initialization remains a problem as well. There is no guaranteed sequence in which statics are created and destroyed…which will cause problems for our logging class, but we will take a more detailed look at this later on.

C++ In Theory: The Singleton Pattern, Part I - The Meyers Singleton
(Page 5 of 5 )

Luckily there is another solution that is very easy to implement and we call it the Meyers Singleton [Meyers]:

class Log {
public:
  static Log& Instance() {
   static Log theLog;
   return theLog;
}
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  Log();          // ctor is hidden
  Log(Log const&);      // copy ctor is hidden
  Log& operator=(Log const&);  // assign op is hidden

  static std::list<std::string> m_data;
};

This construction relies on the fact that function-static objects are only initialized when the function is first being called upon; thus we maintain the benefit of dynamic initialization. (Function-static primitive variables like static int number=100; do get translated during compile time however!)

An additional safeguard is the returned reference instead of the pointer. The caller cannot be tempted to delete the singleton (as was the case when we were returning a pointer). The constructor is hidden, making it impossible for a user to instantiate a Log object; it would still be possible to assign the singleton Log to itself, however, and since this makes no sense we might just as well hide the assignment operator.

  Log::Instance().Write(“Test line”);  // works fine
  Log &myLog = Log::Instance();    // works fine
  Log another = myLog;  // FAILS
  myLog = myLog;    // works until we hide the assign ops!

To wrap it all up, here is an abstract of the Meyers Singleton:

class Singleton {
public:
static Singleton& Instance() {
  static Singleton theSingleton;
  return theSingleton;
}
/* more (non-static) functions here */
private:
Singleton(); // ctor hidden
Singleton(Singleton const&); // copy ctor hidden
Singleton& operator=(Singleton const&); // assign op. hidden
~Singleton(); // dtor hidden
};

In the next article in this series, we will look at how to generalize this class, and at the construction/destruction sequencing problems.

REFERENCES

[Gamma] Design Patterns: E.Gamma, R.Helm, R.Johnson and J.Vlissides.
[Meyers] More Effective C++: S.Meyers.

C++ In Theory: The Singleton Pattern, Part 2
(Page 1 of 4 )

In our second article on the Singleton pattern, J. Nakamura discusses a reusable code version of the pattern.

In the previous article I introduced a design pattern named the “Singleton” as it is described in the book Design Patterns [Gamma]. Design patterns are very useful for describing solutions to common problems that software engineers often encounter. The Singleton pattern is a solution to the desire to have only one object of a class instantiated during the lifetime of your application.

Though design patterns were invented because solutions were often not reusable on the code level, the singleton pattern actually does have a reusable code version. We are going to look at a way to generalize the singleton implementation and how we can use the generalization to deal with construction/destruction sequence problems.

This topic will be covered in four sections:

  1. Singleton Generalization;

  2. Testing Our Generic Implementation;

  3. Singletons are not for Simpletons; and

  4. Resources.

Let's get started.

C++ In Theory: The Singleton Pattern, Part 2 - Singleton Generalization
(Page 2 of 4 )

One of the rules I try to live up to, is that every function and every class should have a single purpose and responsibility. Bolting the Instance() function onto any class you would like to behave as a singleton (and hiding its constructor, destructor, copy constructor and assignment operator) is pretty intrusive and adds additional purpose and responsibility to the interface of that class. You might as well end up with two different versions of the same class: one normal and one singleton version. Would it not be nice to have a singleton class that could add this behavior to any of our classes, whenever we desire it, without having to make any changes?

An object-oriented programmer might be tempted to use class inheritance to solve this problem. After all, if our class is a singleton, should it not be derived from a singleton class?

It is very tricky to get Instance() to create the correct derived object without moving the functionality down into the derived class, and we would still force any derived class to hide the constructor, destructor and assignment operator as well. Defining a separate singleton baseclass becomes a bit superfluous (additional purpose and responsibility will still end up in the derived class), except that it enforces a certain standard to be followed. Additionally you most probably will have to use multiple inheritance to get your implementation right and will probably have multiple headaches (feel free to mail me if you would like me to write about the downsides and upsides of multiple inheritance; diamonds and extension interfaces are great fun!).

Enough threats made… let's look at the solution first.

// singleton.h
#ifndef __SINGLETON_H
#define __SINGLETON_H

template <class T>
class Singleton
{
public:
  static T& Instance() {
   static T _instance;
   return _instance;
  }
private:
  Singleton();          // ctor hidden
  ~Singleton();          // dtor hidden
  Singleton(Singleton const&);    // copy ctor hidden
  Singleton& operator=(Singleton const&);  // assign op hidden
};

#endif
// eof

This implementation is so simple that I really love it. It implements the singleton behavior that we can add onto any class T we provide as the template parameter.

To transform the Log class from the beginning of the previous article to a singleton, without adding an Instance() function and hiding the constructor, destructor etc, I could define it this way:

typedef Singleton<Log> LOG;

And I can write to the log from any location in the application code (as long as it includes the necessary headers):

LOG::Instance().Write(“This is a logline”);

The great benefit of the above implementation is that we never have to change the singleton.h header file and can use it to transform any of our classes into a singleton -- without changing them!

C++ In Theory: The Singleton Pattern, Part 2 - Testing Our Generic Implementation
(Page 3 of 4 )

Let's run a little test to trace object construction and destruction when we use our generic singleton implementation. We expect our singleton class to be created only once!

// main.cpp
#include <stdio.h>
#include “singleton.h”

class MyClass {
public:
MyClass()
: m_Value(0)
, m_ID(++sCount)
{
  (void)printf(“MyClass #%d constructed.\n”, m_ID); 
}

~MyClass() {
(void)printf(“MyClass #%d destructed.\n”, m_ID);
}

  void foo(int value) {
(void)printf(“MyClass%d::foo(0x%08X) called.\n”, m_ID, value);
m_Value=value;
}

  int bar() const
  {
   (void)printf(“MyClass%d::bar() called.\n”, m_ID);
   (void)printf(“… m_Value is: 0x%08X.\n”, m_Value);
   return m_Value;
}

private:
  int m_Value;
  int m_ID;
  static int sCount;
};

int MyClass::sCount=0;

typedef Singleton<MyClass> MyClassSingleton;

void test1() {
  MyClass myObj;
  int val=myObj.bar();
  myObj.foo(++val);
  (void)myObj.bar();
}

void test2() {
  int val=MyClassSingleton::Instance().bar();
  MyClassSingleton::Instance().foo(++val);
  (void)MyClassSingleton::Instance().bar();
}

int main(int argc, char *argv[]) {
  (void)printf(“*** test1 ***\n”);
  test1();
  (void)printf(“*** test1 ***\n”);
  test1();

  (void)printf(\n*** using singleton ***\n”);
  MyClassSingleton::Instance().foo(0x0010);
  (void)printf(“*** test2 ***\n”);
  test2();
  (void)printf(“*** test2 ***\n”);
  test2();

  (void)printf(“\n--- DONE ---\n”);
  return 0;
}

I defined a MyClass trace object that prints a message when it is constructed and when it is destructed. On top of that, every instantiated MyClass receives an unique ID, so that we can see which instantiated object is being manipulated.

Running the code above will give you the following result:

*** test1 ***
MyClass #1 constructed.      #start lifetime MyClass #1 (normal)
MyClass1::bar() called.
... m_Value is: 0x00000000.
MyClass1::foo(0x00000001) called.
MyClass1::bar() called.
... m_Value is: 0x00000001.
MyClass #1 destructed.      #end lifetime MyClass #1
*** test1 ***          #.. we create another one
MyClass #2 constructed.      #start lifetime MyClass #2 (normal)
MyClass2::bar() called.
... m_Value is: 0x00000000.
MyClass2::foo(0x00000001) called.
MyClass2::bar() called.
... m_Value is: 0x00000001.
MyClass #2 destructed.      #end lifetime MyClass #2

*** using singleton ***
MyClass #3 constructed.      #start lifetime MyClass #3 (singleton)
MyClass3::foo(0x00000010) called.    #constructed before we call test()
*** test2 ***
MyClass3::bar() called.
... m_Value is: 0x00000010.
MyClass3::foo(0x00000011) called.
MyClass3::bar() called.
... m_Value is: 0x00000011.

*** test2 ***          #and it stays alive!
MyClass3::bar() called.
... m_Value is: 0x00000011.
MyClass3::foo(0x00000012) called.
MyClass3::bar() called.
... m_Value is: 0x00000012.

--- DONE ---
MyClass #3 destructed.      #singleton destroyed at exit!

Our Singleton template has provided the means to transform MyClass into a Singleton, following the definition/intent as provided in “Design Patterns” [Gamma]: “Ensure a class only has one instance, and provide a global point of access to it.” Great, isn’t it? Well it is...until you start using multiple Singletons that depend on each other.

C++ In Theory: The Singleton Pattern, Part 2 - Singletons are not for Simpletons
(Page 4 of 4 )

While the implementation looks deceptively simple and stable, it harbors a pretty nasty problem: the sequence of static object destruction is not given when an application is being terminated. Imagine two singletons A and B using a logging class L (which is the singleton from the previous article), and after A has used the log in a regular way, the other singleton B causes the application to terminate.

The construction sequence might very well be A – L – C when C fails and terminates the application. So C is destructed first, followed by the Log singleton L, and finally singleton A is destroyed. There is no reason why A won’t attempt to write to the Log while it is being destroyed (destructors are a good location to dump the internal state of an object to the log). But the Log instance was just destroyed! So LOG::Instance().Write() will at best yield an exception or at worst cause your application to terminate the hard way!

The book Modern C++ Design [Alexandrescu] describes this problem in detail and demonstrates multiple solutions, from using the Phoenix Singleton to revive dead singletons, to using Policy template classes to control a Singleton's lifetime. The book is very advanced, very enjoyable and very useful. I have chosen to demonstrate an easy way out to you for now. We will implement a policy option to create either a Meyers Singleton or a Gamma Singleton and leave it at that for now.

If you have read the previous article, you will know that the Meyers Singleton is an implementation that prevents memory leakage. The Gamma Singleton, on the other hand, doesn’t clean up after itself and this comes in handy with our destruction sequence problem. The best way to guarantee our singleton will remain alive to the very end is by simply not destroying it!

Please note that we will depend on the operating system to clean up memory for us, and we have to be very careful not to create a resource leak! Take a look at the Loki library [Alexandrescu] to find out what the complete solution is when the ones I have given you won’t suffice anymore (or when you are curious of course). It will be very trivial to replace these singletons with the Loki ones.

Our singleton needs two different methods of creation. If we externalize these creation methods from the singleton class and provide one of them as a template parameter, the singleton class has become configurable as far as its creation is concerned. This is what policies [Alexandrescu] are all about.

I have constructed a CreateGamma and a CreateMeyers class to demonstrate this concept:

// singleton.h
#ifndef __SINGLETON_H
#define __SINGLETON_H

//
// for a definite implementation of the singleton check out
//
http://sourceforge.net/projects/loki-lib/
//
// or the book “Modern C++ Design” by A.Alexandrescu
//

// This is how a Gamma Singleton would instantiate its object.
template <class T> struct CreateGamma {
  static T* Create() { return new T; }
};

// This is how a Meyers Singleton would instantiate its object.
template <class T> struct CreateMeyers {
  static T* Create() {
   static T _instance;
   return &_instance;
  }
};

// This Singleton class accepts different creation policies.
template <class T, template<class> class CreationPolicy=CreateMeyers>
class Singleton {
public:
  static T& Instance() {
   if (!m_pInstance)
     m_pInstance=CreationPolicy<T>::Create();
   return *m_pInstance;
}

private:
  Singleton();          // ctor hidden
  ~Singleton();          // dtor hidden
  Singleton(Singleton const&);    // copy ctor hidden
  Singleton& operator=(Singleton const&);  // assign op hidden

  static T* m_pInstance;
};

template <class T, template<class> class C>
T* Singleton<T,C>::m_pInstance=0;

#endif // __SINGLETON_H
// eof

Now we can add the following code to our test in main.cpp:

typedef Singleton<MyClass, CreateGamma> MyClassLeaking;

void test3()
{
int val=MyClassLeaking::Instance().bar();
MyClassLeaking::Instance().foo(++val);
(void)MyClassLeaking::Instance().bar();
}

// in main()
  (void)printf(“\n*** using leaking singleton ***\n”);
  MyLeakingSingleton::Instance().foo(0x0100);
  (void)printf(“*** test3 ***\n”);
  test3();
  (void)printf(“*** test3 ***\n”);
  test3();

And see that it yields the desired leakage:

*** using leaking singleton ***
MyClass #4 constructed.      #here our singleton is constructed
MyClass4::foo(0x00000100) called.
*** test3 ***
MyClass4::bar() called.
... m_Value is: 0x00000100.
MyClass4::foo(0x00000101) called.
MyClass4::bar() called.
... m_Value is: 0x00000101.
*** test3 ***          #it lives fine across all calls
MyClass4::bar() called.
... m_Value is: 0x00000101.
MyClass4::foo(0x00000102) called.
MyClass4::bar() called.
... m_Value is: 0x00000102.

--- DONE ---
MyClass #3 destructed.      #the Meyers Singleton is destroyed
           #and our Gamma Singleton is still alive!

At first I thought it would be easy to describe the singleton, until I remembered the troubles I’ve had with construction and destruction sequences of multiple interdependent singletons. Hopefully I have been able to shed some insight into the usage of this "simple" design pattern.

References

[Gamma] Design Patterns: E.Gamma, R.Helm, R.Johnson and J.Vlissides.
[Alexandrescu] Modern C++ Design: A.Alexandrescu.
[Meyers] More Effective C++: S.Meyers.

"C++" 카테고리의 다른 글
  • More on Handling Basic Data Types (0)2007/07/27
  • C++ in theory: Bridging Your Classes with PIMPLs (0)2007/07/27
  • C++ In Theory: The Singleton Pattern (0)2007/07/27
  • <iostream> vs. <iostream.h> (0)2007/07/03
  • C 유저를 위한 C++ 팁 모음 (0)2007/04/30
2007/07/27 16:43 2007/07/27 16:43
Posted by webdizen
Tags C++Keyword C++, Singletion Pattern
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/3101

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1 ... 161 162 163 164 165 166 167 168 169 ... 3009  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • random
  • 메타 데이터
  • 화면 캡처
  • 경연대회
  • 프로그램 중복 실행 방지
  • 톨스토이
  • WORLDCOMP
  • 해네시 VSOP
  • Cataloging
  • Next Statement
  • 데이타 웨어하우스
  • Thread 사용
  • 캐시
  • 심볼 링크
  • Density
  • 다중 데이터베이스
  • memory 크기
  • 전쟁
  • Streaming
  • 강원대

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 학교 과제물중 쓰레드에 대하....
    장진혁 03/17
  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • Lots of students know techn....
    Bobbi35Shannon 02/25
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Rodman®
      • ■ Feel So Good~! ■
      • 까만 나비
      • 나를 가꾸는 시간.
      • 나만의 즐거움~~!
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.