(Ayuda) Programa crashea al analizar una cadena (char *)

Iniciado por Seyro97, 26 Mayo 2015, 22:49 PM

0 Miembros y 1 Visitante están viendo este tema.

Seyro97

Hola. Muy buenas a tod@s. El problema que tengo es algo extraño. Primero enseño el código:

Código (cpp) [Seleccionar]
void String::replaceData(const char *data) {
_num_characters = 0;

while(data[_num_characters] != (char)NULL)
_num_characters += 1;

realloc(_value, _num_characters + 1);
_value[_num_characters] = (char)0;

while(true) {
--_num_characters;

_value[_num_characters] = data[_num_characters];

if(_num_characters == NULL)
break;
}
}


Main

Código (cpp) [Seleccionar]
#include <iostream>

#include "string.h"

int main(int argc, char *argv[]) {
String cadena = "Hola";

cadena.replaceData("Hola, soy un programador");

std::cin.get();
return 0;
}


El problema está en la línea 4, donde el while. Cuando la cadena que le paso por parámetros tiene mas de 16 caracteres, y en el programa presiono enter (el cin.get deja continuar el programa), me sale el siguiente error:
'Debug Assertion Failed, file f:\dd\vctools\crt\crtw32\misc\dbgheap.c, line 1322, expression: _CrtlsValidHeapPointer(pUserData)'

Sé que el error se produce en el while ya que quitandolo, y sustituyendo la variable _num_characters por 17 no me da ese error.

Espero que me puedan ayudar :P Gracias
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

Stakewinner00

A mi no me da ese error... Será algo de tu compilador, de todas formas prueba con esto que debería ser equivalente
   
while( *(data+_num_characters) ) //Mientras no sea NULL
_num_characters ++;

Seyro97

El compilador es el que viene con el ID de VisualStudio 2013.

Me sigue dando el error con la solución propuesta  :-(

Gracias por comentar
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

Seyro97

Pues resulta que era el compilador...

He usado el compilador MinGW (el que viene por defecto con Code::Blocks) y funciona... Es extraño, todos los compiladores deberían seguir las reglas ANSI, por lo que no debería de haber diferencia...
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

Stakewinner00

Ese error es que el debuger de visual studio detecto que se corrompió algo en el heap, pero entonces no es en la línea 4, sino en el realloc si acaso y _value no se que valor es. Como sabes que es en esa línea?

PD: El segundo while con el break ese queda un poco feo en mi opinión

Seyro97

#5
Sé que el error se produce en el while ya que quitandolo, y sustituyendo la variable _num_characters por 17 no me da ese error.

Esa función pertecene a una clase creada por mí llamada String (la estoy haciendo a modo de ejercicio), y _value es la cadena de caracteres que define a un objeto String.

PD:
Código (cpp) [Seleccionar]
for(unsigned int i = 0; i < num_characters; i++)
        _value[i] = data[i];


Esa es mejor, ¿no?
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

x64core

Ese código, el del primer Post, está incompleto o está mal escrito y no compilará en ningun compilador : )

Seyro97

Está claro, el código completo es muy largo, e innecesario (ya que no accedo a partes de ese código no puesto)
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

x64core

Cita de: Seyro97 en 27 Mayo 2015, 00:36 AM
Está claro, el código completo es muy largo, e innecesario (ya que no accedo a partes de ese código no puesto)
Entonces publica algo con lo que la gente que quiere ayudar pueda trabajar, ese es un problema cómun, muchos usuarios vienen a pedir ayuda y publican código incompleto, algunos que responden incluso toman ese código incompleto aunque sea código simple hacen suposiciones innecesarias, crean sus propias versiones, se crea una gran discución y por ultimo muchas veces termina siendo un problema que no tenia que ver con lo descrito, en fin.

Además decir algo como que el error se genera solo en un compilador X es casi como decir que ese compilador tiene un error al generar el código. Tu código es simple y aunque tenga miles de lineas en el main simplemente declaras un clase (?) y llamas a un metodo entonces simple: Publica la declaración de la clase, los constructores, operador y solamente ese metodo que llamas, con eso es suficiente para que alguien pueda trabajar.

Seyro97

#9
Ahí va el código completo:

String.h

Código (cpp) [Seleccionar]
#ifndef _String_h_
#define _String_h_

#include <cstdlib>

#ifndef NULL
#define NULL 0
#endif

class String {
public:
String();
String(const char *init_value);

unsigned int getNumCharacters();
bool isEmpty();

const char *toString();

void append(const char *data);
char charAt(unsigned int index);

void toUpperCase();
void toLowerCase();

void replaceData(const char *data);
void replaceChar(char oldChar, char newChar);
void clear();

private:
char *_value;
unsigned int _num_characters;
};

#endif


String.cpp

Código (cpp) [Seleccionar]
#include "string.h"

String::String() {
_value = (char *)calloc(1, 1);
_num_characters = 1;
}

String::String(const char *init_value) {
unsigned int num_characters = 0;

while(init_value[num_characters] != (char)NULL)
num_characters += 1;

_num_characters = num_characters;
_value = (char *)malloc(num_characters + 1);
_value[num_characters] = (char)0;

for(unsigned int i = 0; i < num_characters; i++)
       _value[i] = init_value[i];
}

unsigned int String::getNumCharacters() {
return _num_characters;
}

bool String::isEmpty() {
return _num_characters == 1;
}

const char *String::toString() {
char *result = (char *)malloc(_num_characters + 1);

   result[_num_characters + 1] = (char)NULL;
   
for(unsigned int i = 0; i <= _num_characters; i++)
result[i] = _value[i];
   
return result;
}

void String::append(const char *data) {
unsigned int num_data_characters = 0;
unsigned int new_num_characters;

while(data[num_data_characters] != (char)NULL)
num_data_characters += 1;

realloc(_value, _num_characters + num_data_characters + 1);

_value[_num_characters + num_data_characters] = (char)NULL;
new_num_characters = _num_characters + num_data_characters;

for(unsigned int i = 0; i < num_data_characters; i++)
       _value[i] = data[i];

_num_characters = new_num_characters;
}

char String::charAt(unsigned int index) {
return _value[index];
}

void String::toUpperCase() {
for(unsigned int i = 0; i <= _num_characters; i++) {
if(_value[i] >= (char)97 && _value[i] <= (char)122)
_value[i] -= (char)32;
}
}

void String::toLowerCase() {
for(unsigned int i = 0; i <= _num_characters; i++) {
if(_value[i] >= (char)65 && _value[i] <= (char)90)
_value[i] += (char)32;
}
}

void String::replaceData(const char *data) {
   unsigned int num_characters = 0;

while(data[num_characters] != (char)NULL)
num_characters += 1;
   
   _num_characters = num_characters;
realloc(_value, num_characters + 1);
_value[num_characters] = (char)0;

for(unsigned int i = 0; i < num_characters; i++)
       _value[i] = data[i];
}

void String::replaceChar(char oldChar, char newChar) {
for(unsigned int i = 0; i <= _num_characters; i++) {
if(_value[i] == oldChar)
_value[i] = newChar;
}
}

void String::clear() {
realloc(_value, 1);
_value[0] = (char)NULL;
_num_characters = 1;
}


main.cpp

Código (cpp) [Seleccionar]
#include <iostream>

#include "string.h"

int main(int argc, char *argv[]) {
String cadena = "";

cadena.replaceData("Hola, soy un programador :'D");

std::cout << cadena.toString();

std::cin.get();
return 0;
}


Solo digo que con MinGW funciona perfectamente y con el compilador de VisualStudio 2013 (no se como se llama), me da errores (no de compilación, sino de ejecución)
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!