fork(3) download
  1. //
  2. //<止まらないalignの再現コード> for 3.51
  3. //
  4. // 1)最初に先頭が偶然8KBにアライメントが合っていたとします
  5. // +----------------+----------------+----------------+----------------+
  6. // | ADDRESS |0x2000(top_) |0x3000 |0x4000 |
  7. // +----------------+----------------+----------------+----------------+
  8. // | DATA | < | |
  9. // +----------------+----------------+----------------+----------------+
  10. //
  11. // 2)1バイト書き込んでからalign(8192)を呼び出します。
  12. // +----------------+----------------+----------------+----------------+
  13. // | ADDRESS |0x2000(top_) |0x3000 |0x4000 |
  14. // +----------------+----------------+----------------+----------------+
  15. // | DATA |* | | |
  16. // +----------------+----------------+----------------+----------------+
  17. //
  18. // 3)4096バイト目の書き込み時にgrowかおこり、
  19. // 今度は先頭が4KBにアライメントが合ったとします。(8KBには合ってない)
  20. // +----------------+----------------+----------------+----------------+
  21. // | ADDRESS |0x5000(top_) |0x6000 |0x7000 |
  22. // +----------------+----------------+----------------+----------------+
  23. // | DATA |****************| < |
  24. // +----------------+----------------+----------------+----------------+
  25. //
  26. // 4)すると書き込もうとしている位置は8KBにアライメントが
  27. // 合っているにもかかわらず1バイト書き込んでしまいます。(db内でgrow直後に書き込んでいるため)
  28. // +----------------+----------------+----------------+----------------+
  29. // | ADDRESS |0x5000(top_) |0x6000 |0x7000 |
  30. // +----------------+----------------+----------------+----------------+
  31. // | DATA |****************|* < |
  32. // +----------------+----------------+----------------+----------------+
  33. //
  34. // 5)8196バイト目にgrowがおこり、先頭が偶然8KBにアライメントが合ったとします。
  35. // +----------------+----------------+----------------+----------------+
  36. // | ADDRESS |0x8000(top_) |0x9000 |0xA000 |
  37. // +----------------+----------------+----------------+----------------+
  38. // | DATA |****************|****************| <
  39. // +----------------+----------------+----------------+----------------+
  40. //
  41. // 6)すると書き込もうとしている位置は8KBにアライメントが
  42. // 合っているにもかかわらず1バイト書き込んでしまいます。
  43. // +----------------+----------------+----------------+----------------+
  44. // | ADDRESS |0x8000(top_) |0x9000 |0xA000 |
  45. // +----------------+----------------+----------------+----------------+
  46. // | DATA |****************|****************|* <
  47. // +----------------+----------------+----------------+----------------+
  48. // (以降繰り返し)
  49. //
  50. //
  51. //<対処法>
  52. //
  53. // CodeArrayのメンバ変数にtop_align_を用意する
  54. // private:
  55. // size_t top_align_;
  56. //
  57. // CodeArrayのコンストラクタでtop_align_をALIGN_PAGE_SIZEで初期化する
  58. // , top_align_( ALIGN_PAGE_SIZE)
  59. //
  60. // growMemory内の2行を以下の様に変更
  61. // uint8 *newAllocPtr = reinterpret_cast<uint8*>(alloc_->alloc(newSize + top_align_));
  62. // uint8 *newTop = getAlignedAddress(newAllocPtr, top_align_);
  63. //
  64. // CodeArray内にアライメントの要求を行う関数を用意しalign()の先頭で呼び出す。
  65. // protected:
  66. // void request_align( size_t align) // 名前は適当です
  67. // {
  68. // if(align < 1 || (align & (align - 1))) throw ERR_BAD_ALIGN;
  69. // if(isAutoGrow() && align > top_align_) {
  70. // // ザイズを変えずにアライメントだけ変更する
  71. // top_align_ = align;
  72. // uint8 *newAllocPtr = reinterpret_cast<uint8*>(alloc_->alloc(maxSize_ + top_align_));
  73. // if (newAllocPtr == 0) throw ERR_CANT_ALLOC;
  74. // uint8 *newTop = getAlignedAddress(newAllocPtr, top_align_);
  75. // for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
  76. // alloc_->free(allocPtr_);
  77. // allocPtr_ = newAllocPtr;
  78. // top_ = newTop;
  79. // }
  80. // }
  81. //
  82. // コレで大丈夫だと思います。
  83. // この関数は継承先から呼び出し可能であると嬉しいです。
  84. // Nバイトnop等、分割できないバイト列でもアライメントしてみたいので。
  85. //
  86. #include <stdint.h>
  87. #include <iostream>
  88. #include <iomanip>
  89. #include <xbyak/xbyak.h>
  90.  
  91. namespace {
  92.  
  93. //----------------
  94. // 例外クラス
  95. //
  96. class InfiniteAllocateException {};
  97.  
  98. //----------------
  99. // 8KB/4KBアライメントのメモリを交互に返すアロケータ
  100. //
  101. class Alloc8K4K : public Xbyak::Allocator {
  102. int alloc_count_;
  103. static int const max_alloc = 15;
  104. public:
  105.  
  106. Alloc8K4K() : alloc_count_( 0) {}
  107.  
  108. Xbyak::uint8 *alloc( size_t size) {
  109. if( alloc_count_ > max_alloc) throw InfiniteAllocateException();
  110.  
  111. intptr_t nap, ap;
  112. if( alloc_count_ % 2) {
  113. // 4K
  114. nap = reinterpret_cast< intptr_t>(new Xbyak::uint8[size + sizeof(intptr_t) + 4096 + 8192 -1]);
  115. ap = ((nap + sizeof(intptr_t) + 8192 - 1) & ~(8192-1)) + 4096;
  116. } else {
  117. // 8K
  118. nap = reinterpret_cast< intptr_t>( new Xbyak::uint8[size + sizeof(intptr_t) + 8192 -1]);
  119. ap = (nap + sizeof(intptr_t) + 8192 - 1) & ~(8192-1);
  120. }
  121. *reinterpret_cast< intptr_t*>(ap - sizeof(intptr_t)) = nap; // 保管
  122. ++alloc_count_;
  123.  
  124. std::cout << std::right << std::dec;
  125. std::cout << "alloc(" << std::setw(2) << alloc_count_ << ")";
  126. std::cout << std::hex;
  127. std::cout << std::setw(16) << ap;
  128. std::cout << std::left << std::dec;
  129. std::cout << " size = " << std::setw(16) << size;
  130. std::cout << std::endl;
  131.  
  132. return reinterpret_cast< Xbyak::uint8*>( ap);
  133. }
  134.  
  135. void free( Xbyak::uint8*p) {
  136. Xbyak::uint8 *nap = reinterpret_cast< Xbyak::uint8*>( *reinterpret_cast< intptr_t*>(reinterpret_cast< intptr_t>(p) - sizeof(intptr_t)));
  137. delete[] nap;
  138. }
  139. };
  140.  
  141. //----------------
  142. // テストコード
  143. //
  144. class TestCode1 : Xbyak::CodeGenerator {
  145. public:
  146. TestCode1( Xbyak::Allocator *alc) : CodeGenerator( 4096, Xbyak::AutoGrow, alc) {
  147. nop();
  148. align( 8192);
  149. std::cout << std::left << std::dec;
  150. std::cout << "getSize()=" << getSize() << std::endl;
  151. }
  152. };
  153.  
  154. } // namespace
  155.  
  156. //----------------
  157. // main
  158. //
  159. using namespace std;
  160. int main() {
  161.  
  162. Alloc8K4K alc;
  163.  
  164. try {
  165. TestCode1 *t1 = new TestCode1(&alc);
  166. delete t1;
  167. } catch( InfiniteAllocateException) {
  168. cout << "Stop : Detect infinite allocation." << endl;
  169. } catch( bad_alloc) {
  170. cout << "Stop : Allocate error." << endl;
  171. } catch( ...) {
  172. cout << "Stop : Unknown error." << endl;
  173. }
  174.  
  175. {
  176. cout << "\nwait." << endl;
  177. int x; cin >> x;
  178. }
  179. }
  180.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty