PDA

Ver la Versión Completa : Stack Overflow


Guillermo80
01-06-2008, 13:57:37
Hola peña, creo que el título de mi hilo lo dice todo...¡ me quedo sin memoria !
El caso es que no entiendo el porqué, ya que me he asegurado de declarar variables tipo LongWord para que no sobrepase el rango.

Mi programa es de codificación de audio, hay un bucle en el que cada vez el número de muestras codificadas va aumentando, hasta que pega el pete cuando lleva 211Mb codificados...Le puse para que codificara un archivo de gran tamaño, para probar un contador de tiempo que le puse a la aplicación, para probar si me contaba bien los minutos, pero claro, no me imaginaba yo que me pegase le excepción a los 38'', momento en el que me doy cuenta de que mi aplicación tiene un fallo que no había detectado.

¿Qué podría hacer? ¿Es posible que LongWord no sea suficiente para controlar el nº de muestras que voy codificando? El problema parece no estar ahí, pero no sé dónde más mirar :(

Khronos
01-06-2008, 14:07:02
Provastes int64? :confused:

Int64= –2^63..2^63–1
Longword= 0..4294967295

Salu2

coso
01-06-2008, 16:16:20
no llamaras recursivamente a alguna funcion dentro del bucle?, tipo :



function calcula(s)
begin
...

for ...

Calcula(s-1);

end;

end;



o en un OnEvent change?

Guillermo80
01-06-2008, 18:58:39
Pues ni lo uno ni lo otro, quiero decir, no tengo puesto nada recursivo, y por otra parte, he probado con el tipo Int64 y tampoco ha resultado :(.

Tengo puesto un TTimer para hacer un reloj que cuente el tiempo de proceso, ¿podría ser este el problema? de todas formas lo puse enabled:=false por probarlo pero tampoco ha resultado.

Ya casi no me quedan ideas por probar, no creo ya que sea cosa de overflow de alguna variable, ahora estoy pensando que es problema de la propia función de mi librería que llama a la función codificadora, ya que al comentar esa línea el proceso de lecturas va perfecto. La función codificadora es de una dll que tengo importada para el programa.

Saludos.

coso
01-06-2008, 19:01:09
si pones el codigo del bucle quiza te podamos ayudar mejor...

pd: usas los breakpoints, watches, ctrl+f3 y el f8 del debugger para saber exactamente cuando te salta el stack overflow?

Guillermo80
01-06-2008, 19:44:44
En el debug me sale en call FreeDeviceContexts, si le doy a ctr+F3 me va al boton que llama la función de codificación, pero no me aclara nada, o sea, en código va a:

procedure TForm1.BtnDecodeClick(Sender: TObject);
begin

DesHabilitaTodo(Sender);
EditDest.Text:=ChangeFileExt(EditDest.Text, '.flac');// ruta destino + nombre fichero flac
DecodeFile(EditDest.Text, EditFileName.Text); // ruta destino.flac, ruta origen.wav

end;

DesHabilitaTodo no es el problema ya que lo he comentado y sigue saltando la excpeción. DecodeFile es la función que contiene el bucle cuyo código es:

while (ok = 1) and (restan > 0) and (BtnDecode.Cancel = false)do
begin
Application.ProcessMessages;
if restan > READSIZE then
begin
necesarias := READSIZE
end
else
begin
necesarias := restan;
end;

progreso := progreso + necesarias;

if(progreso > BarraProgreso.Step) then
begin
BarraProgreso.StepIt;
end;

BlockRead(F_Origen, buffer, tmuestra, transferidas);

if necesarias<tmuestra then
begin
MessageDlg('Error al leer del fichero, las muestras leídas tienen tamaño menor que el tamaño de lectura por muestra', mtError, [mbOk], 0);
ok := 0;
restan := 0;
end
else if ok = 1 then
begin
for i:=0 to (necesarias*channels-1) do
begin
//trabajo ineficiente pero efectivo para sistemas little-endian o big-endian
pcm[i] := FLAC__int32(FLAC__int16(FLAC__int8(buffer[2*i+1]))) shl 8 or FLAC__int16(buffer[2*i]);
end;
//se alimenta el codificador
ok := FLAC__stream_encoder_process_interleaved(pencoder, pcm, necesarias);
end;
restan := restan - necesarias;//necesarias;
end;//while

Si comento la línea que llama a la función FLAC__stream_encoder_process_interleaved, entonces no salta la excepción.

Yo no sé a vosotros, pero yo debugeando con Delphi lo hago a nivel un poco básico y esto del ctrl+F3 y viendo la pila con esas instrucciones en ensamblador no me han aclarado casi nunca los problemas que he tenido...:rolleyes:

coso
01-06-2008, 19:47:25
mmm bueno te aclara exactamente donde te salta la excepcion... y la ruta q lo ha provocado...el ctrl+f12 es para ver la memoria en asm

PD: DesabilitaTodo? he tenido un dejavu? XD
PDD: FLAC etc... son las externas? puedes poner TODA la funcion? (p.e. , pencoder q es?)

si te salta alli y el tipo de argumento pcm es el correcto (pencoder supongo q sera el buffer destino, al cual se le habra asignado memoria etc...) entonces es q la funcion FLAC es la q esta mal :/

PDDD: exactamente, el ctrl+f3 te muestra el stack de funciones, esto es, la pila con las direcciones de memoria de las funciones q se han ido llamando. El stack overflow ocurre cuando esta pila esta llena (sin mem), por eso lo de llamar a funciones autorecursivas q te decia, porque si haces por ejemplo procedure f ; begin f end; se llena el stack hasta provocar excepcion.

otraD: has mirado si el contador i es lo bastante grande para llegar a (necesarias*channels -1 )? si no es el caso, el bucle seria infinito y provocaria el stack overflow.

Guillermo80
01-06-2008, 20:09:42
El Dejavú está justificado, era un problema que tuve hace tiempo que ya solucioné y al cuál creo que tú me ayudaste :).

Bueno, creo que llegado este punto va a ser un follón intentar seguir ahondando más, ya que la función codificadora viene de un código de Visual C++, o sea, la tengo importada a través de una dll.

pencoder es un puntero a un objeto que contiene inicializaciones del codificador e incluso el propio archivo codificado.

La función funciona perfectamente para archivos de un tamaño de hasta 300Mb más o menos, por lo que si fuera fallo de la función el error saldría desde el principio, ¿no? El problema de la pila sin embargo tiene que venir de la función codificadora, sí, se ve que la función no está alojando espacio suficiente para un archivo de suficiente tamaño...no le voy a dar más vueltas creo, ya que en principio la aplicación se usa en un 90% de los casos para pistas sueltas de audio que no suelen superar la media hora, con lo que la codificación es correcta :rolleyes:.

Gracias de nuevo por tu ayuda coso, y por todos los que colaboráis conmigo.

Guillermo80
01-06-2008, 20:12:39
Ah, se me olvidaba, a tu último posdata: necesarias vale como mucho 1024, o sea, que el valor máximo de i será:

1024*2-1

coso
01-06-2008, 20:25:07
ok, pero...

-me referia a tu funcion
-no se tendria q llamar solo una vez a FLAC_stream_encoder_process?
-los valores de pcm estan en el rango correcto? (con el shl 8 quiza crecen mucho)
-no le deberias dar tu la memoria suficiente a pencoder?
-si haces watch de las variables cuando te salta la excepcion, sabras hasta q limites aguanta la FLAC_stream_encoder_process...

bueno, algunas ideas...a ver si al final lo solucionas o algo ;) venga

Guillermo80
01-06-2008, 21:41:36
La función está fuera del bucle for, pero dentro de otro bucle "padre", por lo que se ejecuta muchísimas veces, a cada vez se le pasa sólo un trocito del wav en el array pcm.

Voy a mirar lo que me dices más a fondo, a ver si averiguo exactamente el valor que lo hacer petar, ya mañana te cuento cómo me fue (se me ha hecho un poco tarde :eek:)

De todas formas es bien raro, porque aunque haga el desplazamiento ese fijo que eso está bien porque haciendo esa operación puedo trabajar con codificaciones de hasta 300Mb, el problema viene por la función codificadora FLAC_stream_encoder_process por narices, raro raro.

Un saludo¡¡