Respostas:
De acordo com as especificações, malloc (0) retornará "um ponteiro nulo ou um ponteiro exclusivo que pode ser passado com sucesso para free ()".
Isso basicamente permite que você aloque nada, mas ainda passe a variável "artist" para uma chamada para free () sem se preocupar. Para fins práticos, é praticamente o mesmo que fazer:
artist = NULL;
O padrão C (C17 7.22.3 / 1) diz:
Se o tamanho do espaço solicitado for zero, o comportamento é definido como implementação: um ponteiro nulo é retornado ou o comportamento é como se o tamanho tivesse algum valor diferente de zero, exceto que o ponteiro retornado não deve ser usado para acessar um objeto.
Portanto, malloc(0)
poderia retornar NULL
ou um ponteiro válido que não pode ser desreferenciado . Em ambos os casos, é perfeitamente válido chamá free()
-lo.
Eu realmente não acho que malloc(0)
tenha muita utilidade, exceto nos casos em que malloc(n)
é chamado em um loop, por exemplo, e n
pode ser zero.
Olhando o código no link, acredito que o autor tenha dois conceitos errados:
malloc(0)
retorna sempre um ponteiro válido efree(0)
é ruim.Portanto, ele garantiu que artist
outras variáveis sempre tivessem algum valor "válido". O comentário diz muito: // these must always point at malloc'd data
.
malloc(0)
retornado um ponteiro válido, malloc()
retornar NULL
significa sempre "falha" e 0
não é mais um caso especial, que é mais consistente.
malloc
falha na obtenção de memória são definidas pela implementação, uma implementação poderia simplesmente definir que as alocações tamanho 0 são sempre insatisfatórias ( ENOMEM
) e agora o malloc(0)
retorno 0 (com errno==ENOMEM
) é consistente. :-)
realloc
um ponteiro retornado por malloc(0)
? Você pode realloc((char*)NULL)
?
O comportamento do malloc (0) é específico da implementação. A biblioteca pode retornar NULL ou ter o comportamento malloc regular, sem memória alocada. O que quer que faça, deve ser documentado em algum lugar.
Geralmente, ele retorna um ponteiro válido e exclusivo, mas NÃO deve ser desreferenciado. Observe também que PODE consumir memória, embora não tenha realmente alocado nada.
É possível realocar um ponteiro não nulo malloc (0).
Ter um malloc (0) literalmente não é muito útil. É usado principalmente quando uma alocação dinâmica é zero byte e você não se importou em validá-la.
malloc()
deve manter "informações de manutenção" em algum lugar (esse tamanho do bloco alocado, por exemplo, e outros dados auxiliares). Portanto, se malloc(0)
não retornar NULL
, ele usará memória para armazenar essas informações e, se não for free()
d, constituirá um vazamento de memória.
malloc()
retornará ou retornar NULL
.
malloc(0)
. No entanto, na mesma implementação da biblioteca C padrão, realloc(ptr, 0)
libera ptr
e retorna NULL.
Há uma resposta em outra parte desta página que começa "malloc (0) retornará um endereço de memória válido e cujo intervalo dependerá do tipo de ponteiro ao qual está sendo alocada memória". Esta afirmação está incorreta (não tenho reputação suficiente para comentar diretamente essa resposta, portanto, não posso colocar esse comentário diretamente lá embaixo).
Fazer malloc (0) não alocará automaticamente a memória do tamanho correto. A função malloc não tem conhecimento do que você está lançando seu resultado. A função malloc depende exclusivamente do número do tamanho que você fornece como argumento. Você precisa fazer malloc (sizeof (int)) para obter armazenamento suficiente para armazenar um int, por exemplo, não 0.
malloc(0)
não faz sentido para mim, a menos que o código dependa de comportamento específico da implementação. Se o código foi concebido para ser portátil, ele deve levar em consideração o fato de que um retorno NULL de malloc(0)
não é uma falha. Então, por que não atribuir NULL de artist
qualquer maneira, já que esse é um resultado válido e bem-sucedido, e é menos código, e não fará com que os programadores de manutenção levem tempo para descobrir isso?
malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)
ou malloc(some_variable_which_might_be_zero)
talvez possa ter seus usos, embora, novamente, você precise tomar um cuidado extra para não tratar um retorno NULL como uma falha se o valor for 0, mas um tamanho 0 deve estar OK.
Há muitas respostas semi-verdadeiras por aqui, então aqui estão os fatos concretos. A página de manual para malloc()
diz:
Se size for 0, malloc () retornará NULL ou um valor de ponteiro exclusivo que pode ser passado com êxito para free () com êxito.
Isso significa que não há absolutamente nenhuma garantia de que o resultado malloc(0)
seja único ou não NULL. A única garantia é fornecida pela definição de free()
, novamente, aqui está o que a página de manual diz:
Se ptr for NULL, nenhuma operação será executada.
Portanto, seja qual for o malloc(0)
retorno, ele pode ser transmitido com segurança free()
. Mas o mesmo pode acontecer com um NULL
ponteiro.
Consequentemente, escrever não artist = malloc(0);
é nada melhor do que escrever artist = NULL;
malloc(0)
poderia retornar, digamos, 0x1 e free()
poderia ter uma verificação de caso especial de 0x1, assim como ocorre com 0x0.
NULL
ou um ponteiro exclusivo". em vez disso, "um ponteiro nulo ou um ponteiro para o espaço alocado". Não há um requisito exclusivo . OTOH, retornar um valor especial não exclusivo pode interromper o código que conta com valores únicos. Talvez uma questão de canto para SO.
man
também pode documentar o formulário definido pela implementação usado no * nix. Neste caso isso não aconteça, mas ainda não é uma fonte canônica para C. geral
Por que você não deve fazer isso ...
Como o valor de retorno do malloc depende da implementação, você pode obter um ponteiro NULL ou outro endereço de volta. Isso pode acabar criando estouros de buffer de pilha se o código de manipulação de erros não verificar o tamanho e o valor retornado, levando a problemas de estabilidade (falhas) ou problemas de segurança ainda piores.
Considere este exemplo, onde o acesso adicional à memória via endereço retornado irá corromper a pilha se o tamanho for zero e a implementação retornar um valor não NULL.
size_t size;
/* Initialize size, possibly by user-controlled input */
int *list = (int *)malloc(size);
if (list == NULL) {
/* Handle allocation error */
}
else {
/* Continue processing list */
}
Consulte esta página de codificação segura nos padrões de codificação da CERT, onde peguei o exemplo acima para ler mais.
É certo que nunca vi isso antes, é a primeira vez que vejo essa sintaxe, poderíamos dizer, um caso clássico de exagero de função. Em conjunto com a resposta de Reed, gostaria de salientar que há uma coisa semelhante, que aparece como uma função sobrecarregada realloc
:
realloc(foo, size);
,. Quando você passa um ponteiro não NULL e um tamanho de zero para realloc, o realloc se comporta como se você tivesse chamado free (…)realloc(foo, size);
,. Quando você passa um ponteiro NULL e o tamanho é diferente de zero, o realloc se comporta como se você tivesse chamado malloc (…)Espero que ajude, Atenciosamente, Tom.
malloc (0) retornará NULL ou um ponteiro válido que pode ser passado corretamente para livre. E, embora pareça que a memória para a qual ela aponta é inútil ou não possa ser escrita ou lida, nem sempre é verdade. :)
int *i = malloc(0);
*i = 100;
printf("%d", *i);
Esperamos uma falha de segmentação aqui, mas, surpreendentemente, isso imprime 100! É porque o malloc realmente pede uma grande quantidade de memória quando chamamos malloc pela primeira vez. Toda chamada para malloc depois disso usa a memória desse grande pedaço. Somente após o término desse grande pedaço, é solicitada nova memória.
Uso de malloc (0): se você estiver em uma situação em que deseja que as chamadas subseqüentes sejam mais rápidas, chamar malloc (0) deve fazer isso por você (exceto em casos extremos).
*i
pode não falhar no seu caso, mas é um comportamento indefinido. Cuidado com os demônios nasais!
malloc(0)
isso não mencionado. Nas implementações em que ele retorna um valor não NULL, especialmente em uma compilação DEBUG, ele provavelmente aloca MAIS do que o solicitado e fornece o ponteiro para apenas passar o cabeçalho interno. Isso permite que você tenha uma idéia do uso real da memória, se conseguir isso antes e depois de uma série de alocações. por exemplo: void* before = malloc(0); ... void* after = malloc(0); long long total = after - before;
ou algo assim.
malloc(0)
. Você poderia dizer a qual capítulo você está se referindo também? Fornecer uma cotação exata também seria bom.
No Windows:
void *p = malloc(0);
alocará um buffer de tamanho zero no heap local. O ponteiro retornado é um ponteiro de heap válido.malloc
em última análise, chama HeapAlloc
usando o heap de tempo de execução C padrão, que então chama RtlAllocateHeap
etc.free(p);
usa HeapFree
para liberar o buffer de tamanho 0 no heap. Não liberá-lo resultaria em um vazamento de memória.É realmente bastante útil, e (obviamente IMHO), o comportamento permitido de retornar um ponteiro NULL está quebrado. Um ponteiro dinâmico é útil não apenas para o que aponta, mas também pelo fato de seu endereço ser único. Retornar NULL remove essa segunda propriedade. Todos os mallocs incorporados que eu programa (com bastante frequência) têm esse comportamento.
Não tenho certeza, de acordo com algum código- fonte malloc aleatório que encontrei, uma entrada de 0 resulta em um valor de retorno NULL. Portanto, é uma maneira louca de definir o ponteiro do artista como NULL.
http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html
Aqui está a análise após a execução com a ferramenta de verificação de memória valgrind.
==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740== in use at exit: 0 bytes in 0 blocks
==16740== total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible
e aqui está o meu código de exemplo:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
//int i;
char *p1;
p1 = (char *)malloc(0);
printf("p1 = %p\n", p1);
free(p1);
return 0;
}
Por padrão, 1024 bytes são alocados. Se eu aumentar o tamanho do malloc, os bytes alocados aumentarão em 1025 e assim por diante.
De acordo com a resposta de Reed Copsey e a página de manual do malloc, escrevi alguns exemplos para testar. E eu descobri que malloc (0) sempre dará a ele um valor único. Veja meu exemplo:
char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
puts("Got a null pointer");
else
puts("Got a valid pointer");
A saída será "Tem um ponteiro válido", o que significa que ptr
não é nulo.
malloc(0)
retornará um endereço de memória válido e cujo intervalo dependerá do tipo de ponteiro ao qual está sendo alocada memória. Também é possível atribuir valores à área de memória, mas isso deve estar dentro do alcance do tipo de ponteiro que está sendo usado. Você também pode liberar a memória alocada. Vou explicar isso com um exemplo:
int *p=NULL;
p=(int *)malloc(0);
free(p);
O código acima funcionará bem em um gcc
compilador na máquina Linux. Se você tiver um compilador de 32 bits, poderá fornecer valores no intervalo inteiro, ou seja, -2147483648 a 2147483647. O mesmo se aplica aos caracteres também. Observe que, se o tipo de ponteiro declarado for alterado, o intervalo de valores será alterado independentemente do malloc
tipo de impressão, ou seja,
unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);
p
assumirá um valor de 0 a 255 de char, pois é declarado um int sem sinal.
malloc()
não sabe nada sobre o elenco (que na verdade é inteiramente superfluente em C). A desreferenciação do valor de retorno malloc(0)
chamará um comportamento indefinido.
Apenas para corrigir uma impressão falsa aqui:
artist = (char *) malloc(0);
nunca mais voltará NULL
; não é o mesmo que artist = NULL;
. Escreva um programa simples e compare artist
com NULL
. if (artist == NULL)
é falso e if (artist)
é verdadeiro.