1. Си / Говнокод #19119

    −98

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    void *_band_get_aligned(Band *p, size_t alignment, size_t size)
    {
    	Block     *which;
    	ListNode  *x;
    
    	if (!__mallocsizes_inited) {
    		__malloc_sizes_init();
    	}
    	assert(size <= p->nbpe);
    	if (alignment != _MALLOC_ALIGN) {
    		size_t esize = p->nbpe + SB_OVERHEAD();
    		size_t	   dividend = (alignment / esize);
    		assert(alignment >= _MALLOC_ALIGN);
    
    		if (dividend > p->nalloc
    			|| (alignment != _MALLOC_ALIGN 
          && dividend * esize != alignment)) { /* not an even multiple */
    			errno = EINVAL;
    			return NULL;
    		}
    	}
    
    	if ((which = p->alist) != NULL) {
    		if (alignment != _MALLOC_ALIGN) {
    			x = (ListNode *)_block_memalign(p, which, alignment);
    		}
    		else {
    			x = (ListNode *)_block_mem_malloc_align(p, which);
    		}
    		if (x != NULL) {
    #ifdef STATISTICS
    			p->alloc_counter++;
    #endif
    			x->ln_offset = (char *)which - (char *)x;
    			assert(x->ln_offset < 0);
    			assert(which->navail > 0);
    
    			/*
    		 	* If no more blocks, put this on the depleted-list
    		 	*/
    			if (--which->navail == 0) {
    				Block        *b;
    
    				assert(which->head == NULL);
    				assert(which->prev == NULL);
    
    				/*
    			 	* Simple delete -- which is first.
    			 	*/
    				p->alist = b = which->next;
    				if (b)
    					b->prev = NULL;
    
    				/*
    			 	* insert into d(epleted)list
    			 	*/
    				which->next = b = p->dlist;
    				p->dlist = which;
    				if (b)
    					b->prev = which;
    			}
    			_malloc_stats.m_small_allocmem += p->nbpe;
    			_malloc_stats.m_small_freemem -= p->nbpe;
    
    			return x+1;
    		}
    	}
    
    	if ((which = band_addblk(p)) == NULL) {
    		return 0; /* failed */
    	}
    	assert(which->navail);
    	return _band_get_aligned(p, alignment, size);
    }

    [color=blue]http://sourceforge.net/p/monartis/openqnx/ci/master/tree/trunk/lib/c/alloc/band.c#l346[color] - рекурсия в аллокаторе QNX. Некоторые компиляторы эту рекурсию оптимизируют, некоторые - нет. И когда не оптимизируют, она способна при определенных условия выжрать стек, что приводит к сегфолту, например как тут [color=blue]http://www.openqnx.com/phpbbforum/viewtopic.php?f=7&t=12896&view=print[color]

    Запостил: j123123, 02 Декабря 2015

    Комментарии (10) RSS

    • Рекурсия-то простая, что они цикл не сделали?
      Ответить
      • Причём p, alignment и size даже не меняются... Это просто while (1) { ... }
        Ответить
    • А какие могут быть обстоятельства?
      Исходя из названий функций мне приходит в голову только то, что два потока могут работать с одним Band (что уже странно, учитывая отсутствие блокировок), и между строками 69 и 73 кто-то успел забрать только что добавленную память.
      Ответить
    • > openqnx
      > > In order to compile QNX, you have to install Momentics (6.4.0 is ok) locally
      Эх, схалявить не выйдет... :-/
      Ответить
      • Т.е. он хоть и Open, но собирается только платным тулчайном от настоящего QNX?
        Ответить
        • Оно должно через GCC нормально собираться емнип
          Ответить
          • Благодатная новость! Может и прокатит, в моментиксе же тоже используются какие-то дремучие третий и четвертый gcc.
            Ответить
            • Таки хуй, он почти в каждом мейкфайле инклудит recurse.mk из моментикса.
              Ответить
              • Ну это же всего лишь мейкфайл... Может быть как-то можно эквивалент накостылить?
                Ответить
                • Можно, в понедельник на работке посмотрю что он делает и попробую, авось прокатит. Доки говорят, что он рекурсивно собирает мейкфайлы в поддиректориях, но что-то я не верю, что всё так просто...
                  Ответить

    Добавить комментарий