Pergunta

int main()
{
   char myString = NULL;
   realloc(&myString, 5);
   strncpy((char *)&myString, "test", 5);
}

Parece bom trabalho, mas eu ainda estou um pouco confuso sobre pilha vs heap. Isso é permitido? Se for permitido, faz necessidade myString para ser liberado manualmente ou será liberado quando ele ficar fora do escopo?


Edit: Obrigado pelas respostas, então eu presumo que isso é igualmente ilegal

//I want the code to change myString to "tests"
char myString[5] = "test";
realloc(&myString, strlen(myString)+2);
myString[4] = 's';
myString[5] = '\0';
Foi útil?

Solução

Não, isso é completamente errado. realloc só deve ser usado para a memória realocar alocada por malloc, o que está fazendo obras apenas por acidente, e acabará por falhar terrivelmente

char *myString = malloc(x);
myString = realloc(myString,y);
free(myString)

Você é melhor fora de usar nova e excluir, e ainda melhor fora de usar std :: string, no entanto.

Outras dicas

Alguns problemas com o código que você postou:

  • Sim, você precisa de tudo livre você alocar com malloc e realloc, e as outras funções relacionadas alocação de memória de estilo C.
  • Eu acho que você quis ter char * myString, não car. Passando o endereço de algo na pilha (seu personagem) é completamente errado.
  • Você precisa inicializar o myString ponteiro char para NULL antes de usá-lo em realloc.
  • Você deve estar passando 4 para strncpy não 5, se você tivesse uma seqüência maior que você estaria substituindo memória.
  • Você deve estar liberando o buffer que você criou no seu exemplo
  • Você deve verificar o valor de retorno da chamada realloc. realloc ()

[Quanto valor de retorno do realloc:] Após a conclusão com um tamanho é igual a 0, realloc () retorna uma ponteiro para o (possivelmente movido) espaço alocado. Se o tamanho for 0, quer um ponteiro nulo ou um ponteiro única que pode ser passado com sucesso para livre () é devolvido. Se não houver memória disponível suficiente, realloc () retorna um ponteiro nulo e conjuntos errno para [ENOMEM].

  • re-alocação vai funcionar como malloc quando você passar em NULL:

Se ptr é um ponteiro nulo, realloc () comporta-se como malloc () para o tamanho especificado.

A maneira mais C ++ para fazê-lo:

Você marcado isso como C ++, porém, e é mais tipo seguro de usar C ++ 's novo operador. Embora o novo operador não permite a re-alocação, ele vai trabalhar para alocações e para buffers existentes reutilização (colocação novo).

char *myString = new char[5];
strncpy(myString, "test", 4); 
//...
delete[] myString;

ou mesmo:

#include <string>

//...

std::string str = "test";

fonte de top 2 citações

Isto não deve funcionar. Você está reallocing algo que não foi malloced em primeiro lugar. E não, ele não vai ficar liberado quando ele sai do escopo -. Quando você usa malloc ou realloc, é tudo até você

Update: A sua edição não muda nada - você ainda está tentando realloc algo que não foi malloced em primeiro lugar. Além disso, você não pode ignorar o valor de retorno de realloc - se realloc tem que se mover a memória em outro lugar, você verá que no retorno. Em outras palavras:

char* ptr = malloc(4);
ptr = realloc(ptr, 5);

Depois de realloc, ptr pode ser apontando para um lugar totalmente diferente na memória e continuar a usar o valor original de ptr poderia deixá-lo usando a memória que foi libertado e que não é tão grande quanto você pensa que é.

Isso é perigoso! Esta irá corromper a sua stack. Se você fosse para realloc algo na pilha de uma função que depois voltou para main (), você realmente acabar substituindo o quadro de pilha e retornando em algum lugar diferente main (). Este é um orifício de segurança em potencial.

Tente executar o seguinte. Se ele falhar em realloc, você teve sorte. Você pode causar sérios danos com algo como memcpy (& myString).

int dostuff();

int main()
{
        dostuff();
        return 0;
}

int dostuff()
{
        char myString = NULL;
        realloc(&myString, 5);
        strncpy((char *)&myString, "test", 5);
        return 0;
}

Isto é o que você nunca deve fazer. Tentando free () ou realloc () uma variável de pilha pode levar a um comportamento indefinido, incluindo (mas não limitado a) pilha corrompido (levando ao fluxo imprevisível de controle), corrompido estruturas de serviços heap, memória de usuário corrompido. Você tem sorte se o programa só trava com um AV. Ele pode funcionar em alguns casos, mas você nunca deve tentar fazê-lo.

Regra de ouro: só retornam memória para o gerenciador de memória que foi alocada por diante. Neste caso, não tente voltar a variável de pilha para a pilha de tempo de execução.

O seu programa é sintaticamente válido C ++, mas que irá produzir um comportamento indefinido, porque você passar o endereço de um objeto de pilha para o alocador de heap. Normalmente, isso significa que seu programa irá falhar quando executado.

A pilha e a pilha de duas áreas distintas de memória alocada para o processo de execução de seu programa. A pilha cresce à medida que você digita uma função para manter os seus argumentos e variáveis ??locais, e ele encolhe automaticamente quando você retornar da função. A pilha, por outro lado, é uma região de endereço separado onde a memória podem ser obtidos sob demanda, e deve ser liberado explicitamente quando não é mais necessária.

Se o endereço de uma variável local é passado para realloc (), pode tentar liberar sua memória e alocá-lo em outro lugar. Desde o endereço não é do montão, e realloc () opera na pilha, este irá falhar. A maioria realloc provável () irá detectar o endereço não é da pilha e abortar o programa.


Além disso, o programa exemplo contém alguns erros lógicos.


char myString = NULL;

Você declarar uma variável para segurar um char, não uma string. Uma cadeia de C-estilo tem tipo char*, isto é um apontador de carvão animal.

NULL Além disso, o caractere é atribuído, o endereço zero, o que é convencionalmente atribuído a ponteiros inválidos. Isso compila porque os substitui pré-processador NULL pela 0 literal. Realmente, você armazenar um byte zero no char, que é, também por convenção, o terminador de uma cadeia de estilo C.


realloc(&myString, 5);

Como mencionado acima, isso é ilegal, porque você passar o endereço de um objeto de pilha para o alocador de heap. Este problema permanece em seu segundo exemplo de código.

Além disso, você descartar o valor de retorno. realloc() retorna o endereço onde a nova memória foi alocada. Pode não ser o mesmo endereço como antes. Pode até ser NULL, que é o caminho de realloc() de dizer-lhe que saiu de memória.


strncpy((char *)&myString, "test", 5);

Isso é correto, mas o elenco é redundante.


Aqui está uma versão mais correta de seu programa:


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

int main()
{
   /* allocate space for, say, one character + terminator */
   char* myString = (char*) malloc(2);

   /* some code using myString omitted */

   /* get more space */
   myString = (char*) realloc(myString, 5);

   /* write to the string */
   strncpy(myString, "test", 5);

   /* free the memory */
   free(myString);

   return 0;
}

Em C ++, é melhor realloc evitar () completamente. Por exemplo, você poderia usar algo como o seguinte:


#include <string>

int main()
{
   std::string myString;

   /* some code using myString */

   myString = "test";

   return 0;
}

Você não tem que myString livre, uma vez que está na pilha (que se "libertou" ao sair de escopo).

realloc é ilegal aqui, o endereço tem que ser NULL ou um endereço retornado por uma chamada anterior a realloc, malloc ou calloc.

Cada variável que você declarar estiver na pilha, mesmo um ponteiro:

int * x;

O x variável está na pilha! Ele é do tipo pointer e detém um endereço.

X = (int *) malloc (sizeof (int));

atribui o endereço retornado por malloc à variável x! O conteúdo x é um endereço de memória!

O problema com o que está fazendo é que você está sujando com algo que não é uma variável. Você definiu myString como um char, e, portanto, está tentando mudar seu endereço. Isso é ruim.

O realloc () função não é suposto mudar nada passados ??para ele. É preciso um ponteiro para alguma memória na pilha (ou o ponteiro nulo, se nada já está alocado) e retorna um ponteiro para alguma memória na pilha.

Portanto, você fornece um ponteiro nulo ou um ponteiro para algo alocada por malloc () ou realloc () ou calloc (), e armazenar o ponteiro retornado.

Algo como

char * myString = NULL;
myString = realloc(myString, 5);

vai funcionar, mas você vai querer libertar () myString.

Em C ++, no entanto, usar std :: string.

Em resposta ao seu segundo exemplo de código:

Sim, isso também é ilegal. myString não é alocada com malloc (ou calloc), por isso não pode ser realocado com realloc ou libertados com livre.

Além disso, que realloc não leva um ponteiro para um ponteiro como seu primeiro argumento. Ele leva um ponteiro para a memória alocada, e retorna outro ponteiro (possivelmente diferente). Escrever a chamada como esta em vez disso:

myString = realloc(myString, strlen(myString)+2);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top