Escrevendo em c-corda
-
05-07-2019 - |
Pergunta
meus segfaults código e eu não sei porquê.
1 #include <stdio.h>
2
3 void overwrite(char str[], char x) {
4 int i;
5 for (i = 0; str[i] != '\0'; i++)
6 str[i] = x;
7 }
8
9 int main(void) {
10 char *s = "abcde";
11 char x = 'X';
12 overwrite(s, x);
13 printf("%s\n", s);
14 return 0;
15 }
O depurador gdb me diz, o problema está na linha 6, onde eu quero armazenar um char, em c-corda Isto é o que ele diz (se eu usar dereferencing ponteiro lvalue, é o mesmo problema.):
(gdb) run
Starting program: /tmp/x/x
Breakpoint 1, overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:5
5 for (i = 0; str[i] != '\0'; i++)
(gdb) s
6 str[i] = x;
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x080483e3 in overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:6
6 str[i] = x;
(gdb) q
Estou aprendendo com K & livro R-C e este é simplificada exemplo do capítulo 2.8 (a função remove). Eu não tenho nenhuma idéia de onde está o problema.
Solução
porque char * s = "abcde"; cria corda na memória somente leitura. tente
char s[] = "abcde";
EDIT: Explicação:. Char * é ponteiro, e "ABCDE" é criado na memória somente leitura -> imutável
char [] é matriz, que é inteiramente armazenado em pilha e inicializado a partir da memória, de modo que é mutável
Outras dicas
Quando você define um ponteiro para a string literal , declará-lo como const char *
.
const char *s = "abcde";
Dessa forma, seu compilador reclama quando você tenta enviar essa string para a função de substituição ().
const char *s = "abcde";
char t[] = "fghij";
char x = 'X';
overwrite(s, x); /* oops */
overwrite(t, x); /* ok */
Não discordando, mas apenas para elaborar: Considere o que aconteceria se o compilador permitido isso. Você poderia escrever:
char *s1="abcde";
char *s2="abcde";
s1[0]='x';
puts(s1);
puts(s2);
Se o compilador reconhece que os dois literais são os mesmos e re-usos, mas, em seguida, também permite que a linha 3, a saída seria:
xbcde
xbcde
O que provavelmente não é o que você gostaria. Isto seria particularmente misteriosa se os dois literais foram em partes amplamente separadas do programa.
Experimente:
#include <iostream>
#include <cstring>
using namespace std;
void overwrite(char[], char);
int main(void)
{
char *s = strdup("abcde");
char X = 'X';
overwrite(s, X);
cout << s << endl;
if(s!=NULL)
delete [] s;
return 0;
}
void overwrite(char str[], char x)
{
for(int i=0; str[i]!='\0'; i++)
str[i] = x;
}
Meu palpite é a definição de parâmetros onde você define o tipo como uma matriz de caracteres. Enquanto você está passando um ponteiro para um char
Você pode tentar mudar a primeira linha para o seguinte:
void overwrite(char *str, char x) {
Uma matriz de caracteres e um ponteiro de char não são semanticamente o mesmo.