__attribute __ ((malloc)) против ограничения - PullRequest
0 голосов
/ 06 декабря 2018

Зачем gcc нужно __attribute__((__malloc__))?Разве не должна передаваться та же самая информация, объявляя malloc (и аналогичные функции) возвращающими restrict ed указатели (void *restrict malloc(size_t))?

Кажется, что такой подход был бы лучше, чемне требуя нестандартной функции, это также позволило бы применить ее к функциям, «возвращающимся» через указатель (int malloc_by_arg(void *restrict*retval, size_t size);).

1 Ответ

0 голосов
/ 06 декабря 2018

Даже будучи очень похожим, одна и та же функция дает другую оптимизацию при добавлении restrict или __attribute__((malloc)).Рассматривая этот пример (включенный здесь в качестве ссылки на хороший пример __attribute__((malloc))):

#include <stdlib.h>
#include <stdio.h>
int a;
void* my_malloc(int size)  __attribute__ ((__malloc__))
{
    void* p = malloc(size);  
    if (!p) {    
        printf("my_malloc: out of memory!\n");    
        exit(1);  
}  
return p;
}

int main() {  
    int* x = &a;  
    int* p = (int*) my_malloc(sizeof(int));  
    *x = 0; 
    *p = 1;  
    if (*x) printf("This printf statement to be detected as unreachable 
              and discarded during compilation process\n");  
    return 0;
}

И этот (тот же код без атрибутов):

void* my_malloc(int size);

int a;
void* my_malloc(int size)
{
    void* p = malloc(size);  
    if (!p) {    
        printf("my_malloc: out of memory!\n");    
        exit(1);  
    }  
    return p;
}
int main() {  
    int* x = &a;  
    int* p = (int*) my_malloc(sizeof(int));  
    *x = 0; 
    *p = 1;  
    if (*x) printf("This printf statement to be detected as unreachable 
        and discarded during compilation process\n");  
    return 0;
}

Как и следовало ожидать, код с атрибутом malloc лучше оптимизирован (как с -O3), чем без него.Позвольте мне включить только различия:

без атрибута:

[...]
    call    ___main
    movl    $4, (%esp)
    call    _malloc
    testl   %eax, %eax
    je  L9
    movl    $0, _a
    xorl    %eax, %eax
    leave
    .cfi_remember_state
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
L9:
    .cfi_restore_state
    movl    $LC0, (%esp)
    call    _puts
    movl    $1, (%esp)
    call    _exit
    .cfi_endproc
[...]

с атрибутом:

[...]
    call    ___main
    movl    $4, (%esp)
    call    _my_malloc
    movl    $0, _a
    xorl    %eax, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
[...]

Тем не менее, использование restrict в этом случае бесполезнопри условии, что он не оптимизирует сгенерированный код. Если мы изменим исходный код для использования с restrict:

void *restrict my_malloc(int size);

int a;
void *restrict my_malloc(int size)
{
    void *restrict p = malloc(size);  
    if (!p) {    
    printf("my_malloc: out of memory!\n");    
    exit(1);  
}  
return p;
}
int main() {  
    int* x = &a;  
    int* p = (int*) my_malloc(sizeof(int));  
    *x = 0; 
    *p = 1;  
    if (*x) printf("This printf statement to be detected as unreachable and discarded \
        during compilation process\n");  
    return 0;
}

Код asm точно такой же, как сгенерированный без атрибута malloc:

    [...]
    call    ___main
    movl    $4, (%esp)
    call    _malloc
    testl   %eax, %eax
    je  L9
    movl    $0, _a
    xorl    %eax, %eax
    leave
    .cfi_remember_state
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
L9:
    .cfi_restore_state
    movl    $LC0, (%esp)
    call    _puts
    movl    $1, (%esp)
    call    _exit
    .cfi_endproc
[...]

Таким образом, для функций, подобных malloc / calloc, использование __attribute__((__malloc__)) выглядит более полезным, чем restrict.

__attribute__((__malloc__)) и restrict ведут себя по-разномуоптимизировать код, даже будучи их определения довольно похожи.Это заставляет меня думать, что нет смысла «объединять» их, учитывая, что компилятор выполняет разные оптимизации разными способами.Даже если оба они используются в одном и том же времени, сгенерированный код не будет более оптимизирован, чем наиболее оптимизированный код с одним из них (__attribute__((__malloc__)) или restrict, в зависимости от случая).Так что выбор программиста, чтобы узнать, какой из них лучше подходит в соответствии с его / ее кодом.

Почему __attribute__((__malloc__)) не является стандартным?Я не знаю, но IMO, эти сходства с точки зрения определения и различия с точки зрения поведения не помогают интегрировать оба в стандарт с ясным, хорошо дифференцированным и общим языком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...