Pergunta

Eu tenho este pedaço de código

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main(){
    void *a, *b;

    a = malloc(16);
    b = malloc(16);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);

    a = malloc(1024);
    b = malloc(1024);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);  
}

isto não deveria imprimir o último tamanho do bloco alocado (16 ou 1024)? -Lo em vez imprime 24 e 1032, assim que a quantidade de memória alocada parece ter 8 bytes extras.

O meu problema é (antes de fazer este caso de teste) que eu faço malloc() em uma função (1024 bytes), e retornar o resultado alocado. Ao verificar o tamanho do bloco sobre a função retornar Recebo 516 blocos ... e eu não entendo por que. Eu acho que essa pode ser a razão para a corrupção da memória que ocorre depois de fazer algum processamento sobre os buffers alocados:)

Editar: Eu vi Como posso obter o tamanho de uma matriz de um ponteiro em C? e parece perguntar a mesma coisa, pena de repostagem.

Eu tenho refeito meu exemplo para o meu código mais específico:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

short int * mallocStuff(long int number, short int base){
    short int *array;
    int size=1024;

    array=(short int*)calloc(1,size);
    //array=(short int*)malloc(size);

    return array;
}

int main(){
    short int **translatedArray;

    translatedArray=malloc(4*sizeof(short int));

    int i;
    for(i=0;i<4;i++){
        translatedArray[i]=mallocStuff(0,0);

        if(i>0)
            printf("\n   block size (for a): %p-%p : %i",
                translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
    }

    return 0;
}

E a saída é

   block size (for a): 0x804a420-0x804a018 : 516
   block size (for a): 0x804a828-0x804a420 : 516
   block size (for a): 0x804ac30-0x804a828 : 516

De acordo com o post acima que é maior do que 1024. Estou errado?

Foi útil?

Solução

Você tem um bug. Em vez de:

translatedArray=malloc(4*sizeof(short int));

Você deve ter

translatedArray=malloc(4*sizeof(short int*));

Observe o ponteiro faltando em seu código. Eu suspeito que este é o lugar onde o seu comportamento observado deriva.


Note também que 0x804a420 - 0x804a018 = 1032, não 516. A fórmula translatedArray[i] - translatedArray[i - 1] dá-lhe o número de elementos (ints curtas, ou mais simplesmente, calções) entre os dois endereços, e não o número de bytes .

Outras dicas

Em primeiro lugar, Malloc não garante que duas chamadas malloc sucessivas retornam ponteiros sucessivas.

Em segundo lugar, dependendo de sua arquitetura específica, regras de alinhamento diferentes se aplicam; às vezes você pode pedir para um único byte, mas a arquitetura prefere alocações em intervalos de 8 ou 4 bytes.

Em terceiro lugar, malloc precisa de alguma sobrecarga para armazenar o tamanho do bloco alocado é, etc.

Não faça suposições sobre o que malloc está fazendo além do que diz a documentação!

A função malloc sempre aloca um pouco mais do que você pedir, a fim de armazenar algumas informações de contabilidade. Afinal, quando você chamar free() ele precisa saber quão grande é o bloco é.

Além disso, geralmente implementações malloc irá arredondar o tamanho solicitado para o próximo múltiplo de 8, 16 ou algum outro número ish-round.

Atualizar : A verdadeira resposta para a sua pergunta está na sua utilização do tipo short int. Ao fazer aritmética de ponteiro (subtração) entre ponteiros digitadas, C e C ++ voltar a diferença no número de coisas apontado. Desde que você está apontando para short int, que é de dois bytes de tamanho, o valor devolvido é a metade do que você está esperando.

Por outro lado, malloc sempre aloca um determinado número de bytes , não importa o que você converter o resultado para depois. Tente isto:

    array=(short int*)malloc(sizeof(short int) * size);

Não há garantias de que duas chamadas malloc retornar blocos exatamente embalados juntos - na verdade, não existem quaisquer garantias sobre o resultado em tudo, exceto que se é não NULL ele vai apontar para um bloco de pelo menos tão grande quanto a um solicitado.

Internamente, a maioria dos mallocs armazenar dados trabalhando para ajudá-los a gerenciar o heap. Por exemplo, esses 8 bytes pode conter dois ponteiros - um apontando para o próximo bloco, e um apontando para o bloco anterior. Eu não sei o que esses 8 bytes são, porque você não mencionou que OS você está rodando, mas é perfeitamente normal para malloc usar alguma memória para si nos bastidores.

Alguns alocadores (por exemplo, no Windows) fornecem uma função de biblioteca para descobrir o tamanho do bloco dado um ponteiro, no entanto, outros não, como é um recurso bastante esotérico.

O que retorna malloc depende da implementação de malloc, ea arquitetura. Como outros já disseram, você está garantido para obter pelo menos a quantidade de memória solicitada ou NULL. É também por isso, às vezes, você pode escrever passado o fim de uma matriz, e não obter uma falha de segmentação. É porque você realmente têm acesso válido para esta memória, você simplesmente não sabe disso.

malloc () é normalmente implementado pela divisão da pilha disponível em pedaços de vários tamanhos. No seu caso, malloc () retorna 2 consecutivos 1024 (ou 16) de pedaços de byte. O espaço de 8 bytes que você menciona é usado por malloc () para obter informações de contabilidade.

malloc See de Doug Lea () notas Impl aqui para entender o que está acontecendo por trás das cenas: http://g.oswego.edu/dl/html/malloc.html

malloc() terá a sua própria sobrecarga.

Para não mencionar que não há nenhuma garantia de que 2 alocações consecutivos estará ao lado do outro, para começar.

Se malloc retornos outra coisa senão nulo, então a memória que foi alocada para o seu programa tem o tamanho que você passou para malloc. Tomando a diferença ponteiro entre os valores de retorno de duas chamadas diferença para malloc poderia ter qualquer valor e não tem nada (bem pouco) a ver com o tamanho do bloco do primeiro bloco alocado.

Eu encontrei this..and seleção para o link abaixo para mais informações.

Alocação

Um bloco é atribuído a partir da piscina livre por primeiro converter os bytes solicitados para um índice no conjunto de balde, com a seguinte equação:

necessário = requerido + 8

Se necessário <= 16, então balde = 0

Se necessário> 16, então balde = (log (necessário) / log (2) arredondado para baixo, para o inteiro mais próximo) - 3

O tamanho de cada bloco na lista ancorado pelo balde é o tamanho do bloco = 2 balde + 4. Se a lista no balde é nulo, a memória é alocada usando a sub-rotina sbrk para adicionar blocos para a lista. Se o tamanho do bloco é menor do que uma página, em seguida, uma página é alocada usando a sub-rotina sbrk, e o número de blocos igual ao quociente o tamanho do bloco para o tamanho da página são adicionados à lista. Se o tamanho do bloco é igual ou maior do que uma página, memória necessária é alocada usando a sub-rotina sbrk, e um único bloco é adicionado à lista livre para o balde. Se a lista livre não é vazio, o bloco no topo da lista é retornada para o chamador. O próximo bloco na lista, em seguida, torna-se o novo chefe.

http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm

Antes do ponteiro está o tamanho da seguinte matriz, que é um 32/64 bit inteiro (não sei se assinado ou não assinado)

assim que a quantidade de memória alocada parece ter 8 bytes extras? implementação malloc() em seu sistema parece alocar bytes extras para manter as informações de meta-dados como como seção grande pilha é, o que está começando endereço Info etc.

Apesar de seus varia em diferentes plataformas. Em meus sistemas x86, malloc() alocar min de bytes 17, mesmo que eu estou solicitando malloc(0).

int main(void) {
    int *p = malloc(0);
    if(p == NULL) {
        /* error handling */
    }
    printf("%d\n",p[-1]);/ *it prints 17 bytes */
    /* some code */
    return 0;
}

malloc () pode alocar memória contígua, mas quando o seu malloc telefone () 2 vezes e não pode esperar memória alocada para ser contíguo subtraindo dois ponteiros variabls ...

No entanto memória alocada é a memória virtual que faz parte da implementação do kernel, gerenciamento de memória (VFS) para ser específico. Pode não afetar a funcionalidade do aplicativo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top