É malloc thread-safe?

A function malloc() é reentrante?

    Eu li em algum lugar que se você compilar com -pthread, malloc se torna thread-safe. Eu tenho certeza que sua implementação é dependente, já que malloc é ANSI C e threads não são.

    Se estamos falando de gcc:

    Compile e link com -pthread e malloc () será thread-safe, em x86 e AMD64.

    http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2431a99b9bdcef11/ea800579e40f7fa4

    Outra opinião, mais perspicaz

    {malloc, calloc, realloc, livre, posix_memalign} do glibc-2.2 + são thread safe

    http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2005-07/0323.html

    Pergunta: “é reinput malloc”?
    Resposta: não, não é. Aqui está uma definição do que faz uma reinput de rotina.

    Nenhuma das versões comuns do malloc permite que você reinseri-lo (por exemplo, de um manipulador de sinal). Observe que uma rotina reentrante pode não usar bloqueios, e quase todas as versões malloc existentes usam bloqueios (o que os torna thread-safe) ou variables ​​globais / estáticas (o que os torna inseguros e não reentrantes).

    Todas as respostas até agora respondem “é malloc thread-safe?”, O que é uma questão completamente diferente. Para essa pergunta, a resposta é que depende da sua biblioteca de tempo de execução e, possivelmente, dos sinalizadores do compilador que você usa. Em qualquer UNIX moderno, você obterá um malloc thread-safe por padrão. No Windows, use /MT , /MTd , /MD ou /MDd sinalizadores para obter biblioteca de tempo de execução thread-safe.

    Aqui está um trecho de malloc.c da glibc:

    Segurança de thread: thread-safe a menos que NO_THREADS seja definido

    supondo que NO_THREADS não esteja definido por padrão, malloc é thread safe pelo menos no linux.

    Esta é uma questão bastante antiga e eu quero trazer frescor de acordo com o estado atual das coisas.

    Sim, atualmente malloc() é thread-safe.

    Do Manual de Referência da Biblioteca GNU C de glibc-2.20 [released 2014-09-07] :

    void * malloc (size_t size)

    Preliminar: MT-Safe | …

    … 1.2.2.1 Conceitos de segurança POSIX:

    … As funções MT-Safe ou Thread-Safe são seguras para chamar na presença de outros threads. MT, em MT-Safe, significa Multi Thread.

    Ser MT-Safe não implica que uma function seja atômica, nem que use qualquer um dos mecanismos de synchronization de memory que o POSIX exponha aos usuários. É até possível que chamar funções MT-Safe em seqüência não produza uma combinação MT-Safe. Por exemplo, ter um thread chama duas funções MT-Safe uma após a outra não garante um comportamento equivalente à execução atômica de uma combinação de ambas as funções, já que chamadas simultâneas em outros threads podem interferir de maneira destrutiva.

    Otimizações de todo o programa que poderiam inline funções através de interfaces de bibliotecas podem expor um reordenamento inseguro, e assim a execução de inlining na interface da Biblioteca GNU C não é recomendada. O status de segurança MT documentado não é garantido na otimização de todo o programa. No entanto, funções definidas em headers visíveis pelo usuário são projetadas para serem seguras para inlining.

    Sim, em POSIX.1-2008 malloc é thread-safe.

    2.9.1 Segurança de roscas

    Todas as funções definidas por este volume de POSIX.1-2008 devem ser thread-safe, exceto que as seguintes funções1 não precisam ser thread-safe.

    [uma lista de funções que não contém malloc ]

    Se você estiver trabalhando com o GLIBC, a resposta é: Sim, MAS.

    Especificamente, sim, MAS, por favor, esteja ciente que enquanto malloc e free são thread-safe, as funções de debug não são.

    Especificamente, as funções extremamente úteis mtrace (), mcheck () e mprobe () não são seguras para threads . Em uma das respostas mais curtas e diretas que você verá em um projeto GNU, isso é explicado aqui:

    https://sourceware.org/bugzilla/show_bug.cgi?id=9939

    Você precisará considerar técnicas alternativas, como ElectricFence, valgrind, dmalloc, etc.

    Então, se você quer dizer, “são as funções malloc () e free () threadsafe”, a resposta é sim. Mas se você quer dizer, “é todo o malloc / suite grátis threadsafe”, a resposta é NÃO.

    Depende de qual implementação da biblioteca de tempo de execução C você está usando. Se você estiver usando o MSVC, por exemplo, há uma opção de compilador que permite especificar com qual versão da biblioteca você deseja construir (ou seja, uma biblioteca de tempo de execução que suporte multi-threading sendo segura ou não).

    Não, não é thread-safe. Na verdade, pode haver uma function malloc_lock() e malloc_unlock() disponível em sua biblioteca C. Eu sei que estes existem para a biblioteca Newlib. Eu tive que usar isso para implementar um mutex para o meu processador, que é multi-threaded em hardware.

    malloc e free não são reentrantes, porque usam uma estrutura de dados estática que registra quais blocos de memory são livres. Como resultado, nenhuma function de biblioteca que aloque ou libere memory é reentrante.

    Resposta curta: sim, a partir de C11, que é a primeira versão do padrão C que inclui o conceito de threads, malloc e amigos são obrigados a ser thread-safe. Muitos sistemas operacionais que incluíam threads e um tempo de execução C faziam essa garantia muito antes do padrão C, mas eu não estou preparado para jurar para todos . No entanto, malloc e amigos não são e nunca foram obrigados a ser reentrantes.

    Isso significa que é seguro chamar malloc e free vários threads simultaneamente e não se preocupar em travar, contanto que você não esteja quebrando nenhuma das outras regras de alocação de memory (por exemplo, chamar uma vez e somente uma vez em cada ponteiro retornado por malloc ). Mas não é seguro chamar essas funções de um manipulador de sinal que possa ter interrompido uma chamada para malloc ou free no encadeamento que manipula o sinal. Às vezes, usando funcionalidades além do ISO C, você pode garantir que o thread que manipula o sinal não interrompeu uma chamada para malloc ou free , por exemplo com sigprocmask e sigpause , mas tente não fazer isso a menos que você não tenha outra opção, porque é difícil fique perfeitamente certo.


    Resposta longa com citações: O padrão C adicionou um conceito de threads na revisão de 2011 (link é para documentar o N1570, que é a aproximação mais aproximada do texto oficial da norma 2011 que está publicamente disponível gratuitamente). Nessa revisão, a seção 7.1.4, parágrafo 5, declara:

    A menos que explicitamente declarado de outra forma nas descrições detalhadas que se seguem, as funções da biblioteca evitarão as corridas de dados da seguinte forma: Uma function de biblioteca não deve acessar direta ou indiretamente objects acessíveis por encadeamentos que não sejam o encadeamento atual, a menos que os objects sejam acessados ​​direta ou indiretamente através dos argumentos da function. . Uma function de biblioteca não deve modificar direta ou indiretamente objects acessíveis por encadeamentos que não sejam o encadeamento atual, a menos que os objects sejam acessados ​​direta ou indiretamente por meio dos argumentos não-constantes da function. As implementações podem compartilhar seus próprios objects internos entre segmentos, se os objects não estiverem visíveis para os usuários e estiverem protegidos contra as raças de dados.

    [nota de rodapé: Isso significa, por exemplo, que uma implementação não tem permissão para usar um object estático para fins internos sem synchronization porque pode causar uma corrida de dados mesmo em programas que não compartilham explicitamente objects entre threads. Da mesma forma, uma implementação do memcpy não tem permissão para copiar bytes além do comprimento especificado do object de destino e, em seguida, restaurar os valores originais porque isso poderia causar uma corrida de dados se o programa compartilhasse esses bytes entre os threads.]

    Pelo que entendi, esta é uma maneira prolixa de dizer que as funções de biblioteca definidas pelo padrão C precisam ser seguras para thread (no sentido usual: você pode chamá-las de vários threads simultaneamente, sem fazer qualquer bloqueio por conta própria , desde que eles não acabem colidindo com os dados passados ​​como argumentos) a menos que a documentação de uma function específica diga especificamente que não é.

    Então, 7.22.3p2 confirma que malloc, calloc, realloc, alignment_alloc e free em particular são thread-safe:

    Para fins de determinar a existência de uma corrida de dados, as funções de alocação de memory se comportam como se acessassem apenas locais de memory acessíveis por meio de seus argumentos e não outros armazenamentos de duração estática. Essas funções podem, no entanto, modificar visivelmente o armazenamento que elas alocam ou desalocam. Uma chamada para liberar ou realocar que desaloca uma região p de memory sincroniza com qualquer chamada de alocação que aloca toda ou parte da região p. Essa synchronization ocorre após qualquer access de p pela function deallocating e antes de qualquer access por function de alocação.

    Compare o que diz sobre strtok, que não é e nunca foi thread-safe, em 7.24.5.8p6 :

    A function strtok não é necessária para evitar corridas de dados com outras chamadas para a function strtok.

    [nota de rodapé: A function strtok_s pode ser usada para evitar corridas de dados.]

    (comente a nota de rodapé: não use strtok_s , use strsep .)

    Versões mais antigas do padrão C não diziam nada sobre segurança de thread. No entanto, eles disseram algo sobre a reinput, porque os sinais sempre fizeram parte do padrão C. E é isso que eles disseram, voltando ao padrão ANSI C original de 1989 (este documento tem um texto quase idêntico a uma numeração de seções muito diferente da norma ISO C que saiu no ano seguinte):

    Se o sinal [a] ocorrer diferente do resultado de chamar a function abortar ou levantar, o comportamento é indefinido se o manipulador de sinais chamar qualquer function na biblioteca padrão diferente da própria function de sinal ou se referir a qualquer object com duração de armazenamento estático diferente do que atribuindo um valor a uma variável de duração de armazenamento estático do tipo volátil sig_atomic_t. Além disso, se tal chamada à function de sinal resultar em um retorno SIG_ERR, o valor de errno é indeterminado.

    Que é uma maneira prolixa de dizer que as funções da biblioteca C não precisam ser reentrantes como regra geral. Um texto muito semelhante ainda aparece em C11, 7.14.1.1p5 :

    Se [a] ocorrer um sinal diferente do resultado de chamar a function abortar, o comportamento é indefinido se o manipulador de sinal fizer referência a qualquer object com duração de armazenamento estático ou de encadeamento que não seja um object atômico livre de bloqueios que não seja atribuindo um valor para um object declarado como volátil sig_atomic_t, ou o manipulador de sinal chama qualquer function na biblioteca padrão diferente da function abort, a function _Exit, a function quick_exit, ou a function signal com o primeiro argumento igual ao número do sinal correspondente a o sinal que causou a invocação do manipulador. Além disso, se tal chamada à function de sinal resultar em um retorno SIG_ERR, o valor de errno é indeterminado.

    [nota de rodapé: Se algum sinal for gerado por um manipulador de sinal asynchronous, o comportamento é indefinido.]

    O POSIX requer muito mais tempo, mas ainda é curto comparado ao tamanho geral da biblioteca C , lista de funções que podem ser chamadas com segurança de um “manipulador de sinais asynchronous” e também define com mais detalhes as circunstâncias sob as quais um sinal pode “ocorrer do que como o resultado de chamar a function de abortar ou aumentar. ” Se você estiver fazendo algo não trivial com sinais, provavelmente está escrevendo código destinado a ser executado em um SO com a natureza Unix (em oposição ao Windows, MVS ou algo embutido que provavelmente não tem uma implementação hospedada completa de C em o primeiro lugar), e você deve se familiarizar com os requisitos POSIX para eles, bem como com os requisitos ISO C.