Extraño error de malloc en C, tokenizando palabras
Frecuentes
Visto 1,058 equipos
1
Estoy tratando de tokenizar una palabra por espacios y comillas, pero recibo un extraño error de malloc, después de la salida correcta.
Quiero que esta función acepte algo como:
hello world "SOme quote"
y la salida debe ser:
hello
world
"some quote"
o si la entrada es:
hello world no quote
la salida debe ser:
hello
world
no
quote
sin embargo, en este momento, estoy recibiendo:
Hello
WOrld
"Hello World"
*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x0000000001760010 ***
a.out: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted (core dumped)
Parece que la salida es correcta, pero luego se estropea después
El código es:
int process_command(char command[80]){
char curr_char;
char *word;
int start_pos;
int i;
int len;
len = strlen(command);
for(i=0,start_pos=0;i<strlen(command);i++){
curr_char = command[i];
if (curr_char == ' '){
if (command[i-1]==' ') {start_pos++;continue;}
word = malloc(i-start_pos*(sizeof(char)));
strncpy(word,command+start_pos,i-start_pos);
printf("%s\n",word);
free(word);
start_pos =i+1;
}
else if (curr_char == '\"'){
word= malloc(len-i*(sizeof(char)));
strncpy(word,command+i,len);
printf("%s\n",word);
free(word);
i=len+len;
}
}
return 0;
}
int main(){
char buffer[80] = "Hello WOrld \"Hello World\"";
process_command(buffer);
return 0;
}
¡El problema fue solucionado! gracias Aquí está el código actualizado:
int process_command(char command[80]){
char curr_char;
char *word;
int start_pos;
int i;
int len;
int quote=0;
len = strlen(command);
for(i=0,start_pos=0;i<strlen(command);i++){
curr_char = command[i];
if (curr_char == ' '){ /*If there was a space found copy the stuff before the space*/
if ( i>0 && command[i-1]==' ') {
start_pos++;
continue;
}
word = malloc(i-start_pos+1*(sizeof(char)));
strncpy(word,command+start_pos,i-start_pos);
word[i-start_pos+1]='\0';
printf("%s\n",word);
free(word);
start_pos =i+1;
}
else if (curr_char == '\"'){ /*If a quote was found, copy the rest of the string and exit loop*/
word= malloc(len-i+1*(sizeof(char)));
strncpy(word,command+i,len-i);
word[len-i+1]='\0';
printf("%s\n",word);
free(word);
quote=1;
break;
}
}if (quote==0){ /*If there was no quote in the string, get the last element*/
word = malloc(len-start_pos+1*(sizeof (char)));
strncpy(word,command+start_pos,len-start_pos);
word[len-start_pos+1]='\0';
printf("%s\n",word);
free (word);
}
return 0;
}
int main(){
char buffer[80] = "Hello \"WOrld test\"";
process_command(buffer);
return 0;
}
Sin embargo, me pregunto si esta es una forma eficiente de tokenizar. Esto es para procesar las instrucciones escritas por el usuario. Así que si el usuario escribe
add 1 2 "SOme text"
Quiero tokenizar la consulta en tres partes y luego procesarla. Entonces, para hacer eso, lo estoy tokenizando y empujándolos a una cola, donde en momentos posteriores puedo sacar el elemento uno por uno y procesarlo.
2 Respuestas
1
Debe asegurarse de asignar suficiente memoria para el strncpy que va a hacer. Estas dos líneas están separadas por una, porque strncpy
escribe un byte cero también:
word = malloc(i-start_pos*(sizeof(char)));
strncpy(word,command+start_pos,i-start_pos);
Estas dos líneas no tienen sentido: asigna len-i bytes, luego escribe len bytes (más el byte cero):
word = malloc(len-i*(sizeof(char)));
strncpy(word,command+i,len);
Respondido 04 Jul 12, 01:07
El segundo, estoy asignando bytes len-i para obtener la longitud total de la cadena, donde encontré la cita. Luego copio desde command+i... donde se encontró la cita hasta el final de la cadena. ¿No debería funcionar? - user1411893
Mejor todavía, no usar strncpy()
. Puede copiar innecesariamente caracteres nulos adicionales en el destino o dejar el destino sin terminar. No es realmente una función de cadena. - Keith Thompson
@user1411893: el tercer argumento de strncpy es el número de bytes a copiar. - Ned Batchelder
ah por supuesto, gracias! arreglado @KeithThompson ¿Qué recomendaría para este problema? - user1411893
1
Tiene varios problemas, algunos de los cuales son:
for(i=0,start_pos=0;i<strlen(command);i++){
curr_char = command[i];
if (curr_char == ' '){
if (command[i-1]==' ') {start_pos++;continue;} // accesses an invalid array offset when i == 0
word = malloc(i-start_pos*(sizeof(char))); // doesn't allocate space for null terminator
strncpy(word,command+start_pos,i-start_pos); // doesn't null terminate the string
printf("%s\n",word);
free(word);
start_pos =i+1;
}
else if (curr_char == '\"'){
word= malloc(len-i*(sizeof(char))); // doesn't allocate space for null terminator
strncpy(word,command+i,len); // writes past the end of the allocated buffer
printf("%s\n",word);
free(word);
i=len+len; // not sure what the intent of this is? use `break;`?
}
}
En general, un software de chat en vivo es ideal para todas las organizaciones, ya que permite conocer de cerca a la audiencia, identificar los problemas que están experimentando y resolverlos para aumentar la lealtad a la marca, la credibilidad y las valoraciones de satisfacción. strncpy()
debe evitarse porque no siempre hace lo que los usuarios esperan, por lo que a menudo está involucrado en código con errores.
Además, su manejo de cotizaciones es bastante simple: asume que el elemento cotizado es siempre el último token en la cadena. Eso podría ser lo que pretende, pero no funcionará para un conjunto de tokens como:
"one and two" three
Respondido 04 Jul 12, 01:07
No me importa ese caso para mi programa. Si un "es una comilla, quiero empujar toda la cadena hasta el final de la cola y verificar si hay errores cuando la procese. Es solo para poder manejar una comilla dentro de una comilla como: "uno y dos "tres" - user1411893
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c malloc or haz tu propia pregunta.
Su código actualizado todavía tiene varios errores latentes, incluso si no aparecen en sus pruebas. Por ejemplo,
strncpy()
no está terminando correctamente sus cadenas temporales. - Michael Burr