Pergunta

Então eu tenho um pouco de código em C:

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

/* putting one of the "char*"s here causes a segfault */
void main() {
  char* path = "/temp";
  char* temp;
  strcpy(temp, path);
}

Isso compila, corre, e se comporta como parece.No entanto, se um ou ambos os ponteiros de caracteres é declarada como variável global, strcpy resulta em uma falha de segmentação.Por que isso acontece?Evidentemente, há um erro no meu entendimento do escopo.

Foi útil?

Solução

Como outras pôsteres mencionados, a raiz do problema é que temp é inicializado. Quando declarada como uma variável automática na pilha que vai conter o que o lixo passa a ser em que local da memória. Aparentemente, para o compilador + CPU OS + você está executando, o lixo naquele local é um ponteiro válido. O strcpy "sucede" em que não segfault, mas realmente copiado uma corda para algum local arbitrário em outro lugar na memória. Este tipo de ataques problema de corrupção de memória do medo nos corações dos programadores C em todos os lugares, pois é extremamente difícil de depurar.

Quando você mover a declaração da variável temp para escopo global, ele é colocado na seção BSS e zerado automaticamente. As tentativas de excluir a referência * temporário resultar em seguida, um segfault.

Quando você move caminho * até âmbito global, em seguida, * temporários move-se um local na pilha. O lixo naquele local não é, aparentemente, um ponteiro válido, e assim dereferencing resultados * temporários em um segfault.

Outras dicas

A variável temp não apontam para qualquer armazenamento (memória) e é inicializado.

Se temp é declarada como char temp[32]; então o código iria funcionar, não importa onde ela é declarada. No entanto, existem outros problemas com a declarar temperatura com um tamanho fixo como essa, mas isso é uma questão para outro dia.

Agora, por que ele falhar quando declarou globalmente e não localmente. Sorte ...

Quando declarado localmente, o valor da temperatura é proveniente de que sempre que o valor pode ser na pilha naquele momento. É sorte que ele aponta para um endereço que não causar um acidente. No entanto, é destruindo a memória usado por outra pessoa.

Quando declarada globalmente, na maioria dos processadores estas variáveis ??serão armazenados em segmentos de dados que usarão demanda zero páginas. aparece assim char *temp como se fosse declarado char *temp=0.

Você esqueceu de alocar e temperatura initialize:

temp = (char *)malloc(TEMP_SIZE);

Apenas certifique-se TEMP_SIZE é grande o suficiente. Você também pode calcular isso em tempo de execução, certifique-se o tamanho é suficiente (deve ser pelo menos strlen (path))

Como mencionado acima, você se esqueceu de alocar espaço para Temp. Eu prefiro strdup para malloc+strcpy. Ele faz o que você quer fazer.

Não - isso não funciona independentemente das variáveis ??- ele só parece que ele fez, porque você tem (un) sorte. Você precisa alocar espaço para armazenar o conteúdo da corda, em vez de deixar a variável uninitialised.

variáveis ??uninitialised na pilha vão estar apontando para praticamente locais aleatórios da memória. Se esses endereços acontecer de ser válida, o seu código pisará em todo o que estava lá, mas você não obterá um erro (mas pode ter bugs relacionados desagradável de corrupção de memória em outro lugar no seu código).

Globals forma sistemática, não porque eles geralmente prepare-se para padrões específicos que apontam para a memória não mapeada. A tentativa de excluir a referência estes lhe dá uma segfault imediatamente (o que é melhor - deixando-o mais tarde para faz com que o bug muito difícil de rastrear).

Eu gostaria de reescrever primeiro fragmento de Adão como

// Make temp a static array of 256 chars
char temp[256];
strncpy(temp, sizeof(temp), path);
temp[sizeof(temp)-1] = '\0';

Dessa forma, você:

1. don't have magic numbers laced through the code, and
2. you guarantee that your string is null terminated.

O segundo ponto é a perda do último caractere da seqüência de origem se ele for> = 256 caracteres.

A parte importante notar que:
string de destino destino deve ser grande o suficiente para receber a cópia.
Na sua situação temp não tem memória alocada para copiar para.

Copiado da página de man de strcpy:

DESCRIPTION
   The  strcpy()  function  copies the string pointed to by src (including
   the terminating '\0' character) to the array pointed to by  dest.   The
   strings  may not overlap, and the destination string dest must be large
   enough to receive the copy.

Você está invocando um comportamento indefinido, desde que você não está inicializando a variável temp. Ele aponta para uma localização aleatória na memória, para que o seu programa pode trabalho, mas o mais provável é que segfault. Você precisa ter o seu string de destino ser um array, ou tê-lo apontar para memória dinâmica:

// Make temp a static array of 256 chars
char temp[256];
strncpy(temp, 256, path);

// Or, use dynamic memory
char *temp = (char *)malloc(256);
strncpy(temp, 256, path);

Além disso, o uso strncpy() vez de strcpy() a estouros de buffer a evitar.

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