Estoy bastante seguro de que no debe buscar todos los BLOB en una matriz al comienzo del procedimiento. Dado que lee los datos BLOB y nunca cierra ningún localizador de lob, Oracle tiene que mantener toda esta información en la memoria. Supongo que este es un caso de sobrellenado de memoria.
Prueba esto en su lugar:
CURSOR cc IS (SELECT ...)
BEGIN
OPEN cc;
LOOP
FETCH cc
INTO l_fname, l_blob;
EXIT WHEN cc%NOTFOUND;
l_blob_len := DBMS_LOB.getlength(l_blob);
DBMS_OUTPUT.PUT_LINE(l_blob_len);
l_file := UTL_FILE.fopen('BLOBS', l_x || '_' || l_fname, 'w', 32767);
l_pos := 1;
l_x := l_x + 1;
WHILE l_pos < l_blob_len LOOP
DBMS_LOB.READ(l_blob, l_amount, l_pos, l_buffer);
UTL_FILE.put_raw(l_file, l_buffer, TRUE);
l_pos := l_pos + l_amount;
END LOOP;
UTL_FILE.fclose(l_file);
END LOOP;
CLOSE cc;
END;