elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 7 8 9 10 11 12 13 [14] 15 16 17 18 19 20 21 22 23 24
131  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 17 Abril 2020, 17:46 pm
A diferencia de los punteros near, los far son más simples: los 2 bytes más significativos contienen el segmento, y los 2 menos significativos el desplazamiento. Las operaciones que hago en el código que puse son simplemente extraer los el conjunto de dos bytes que interesen, para obtener sus componentes; o bien, juntarlos en un único número de 4 bytes, para generar el puntero far.

Por cierto, si me permites la curiosidad ¿por que en vez de hacer una rotacion de 16 bits (puntero_far >> 16) no multiplicar simplemente el segmento por 0x10?

Bueno, en realidad no estoy haciendo una rotación (de hecho, C no proporciona operadores para eso) sino un simple desplazamiento a la derecha. Con esto, como decía arriba, obtengo el valor los 2 bytes más significativos. Multiplicar por 0x10 daría un resultado completamente diferente. La operación a nivel de bits equivalente a esa muliplicación sería (puntero_far << 4). La operación aritmética equivalente al desplazamiento que hago sería dividir entre 0x10000 (65536). De cualquier forma, las operaciones a nivel de bits, además de que suelen ser más eficientes que las aritméticas, en estos casos me parece que hacen más explícito lo que se quiere hacer.

Pasé por alto un mensaje anterior. ¿Esás generando un archivo COM? Porque si es así, a eso se debe el error. Los COM no pueden hacer llamadas far, dado que están limitados a un sólo segmento. Aunque sí que hay forma de acceder a datos en otros segmentos (teniendo que calcularlos manualmente, y directamente en ensamblador, no en C), no es así con las llamadas far. Lo normal sería que el linker diera error, diciendo que el archivo contiene referencias reubicables (relocatable), pero es posible que algunos simplemente conviertan las llamadas far a near, o directamente ignoren el problema y las dejen far, lo cual ocasionará que el programa falle durante la ejecución.
132  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 15 Abril 2020, 00:59 am
la pregunta precisa seria: ¿como almaceno segmentselector y offset en el puntero, para realizar la llamada far?

No sé si entendí bien lo que quieres, pero si ya tienes el puntero far y necesitas el offset y el segmento, lo puedes hacer así:

Código
  1. unsigned int segmento = (unsigned int)((unsigned long)puntero_far >> 16);
  2. unsigned int offset = (unsigned int)((unsigned long)puntero_far & 0xFFFF);

Si lo quieres es lo opuesto:

Código
  1. // Editado: la funcion que deseas llamar no recibe parametros:
  2.  
  3. //puntero_far = (void far (*)(int))(((unsigned long)segmento << 16) + offset);
  4. puntero_far = (void far (*)())(((unsigned long)segmento << 16) + offset);

Como los tamaños de los tipos varían de un compilador a otro, puede que necesites cambiar long por algún otro tipo que ocupe 32 bits, y poner __far en lugar de far.

En cuanto a tu pregunta original, C no tiene concepto de punteros near, far, modelos de memoria, ni nada por el estilo, por lo que todo esto depende totalmente del compilador. Lo más cercano a Open Watcom que usé es el Watcom C normal, pero hace mucho de eso, y además no sé qué tanto difieran, pero el código que pones tendría que funcionar. En general, usar la palabra "far" (o __far, o cualquier otro equivalente en el compilador que se use) ya debería bastar para llamar a estas funciones. No sé cuál sea el problema aquí, pero yo vería si el Open Watcom no hace algo "raro" al usar __far. Lo mejor en estos casos es checar el ensamblador generado por el compilador, ya sea mediante algún flag, si lo tiene, o desensamblando el ejecutable.
133  Programación / Programación C/C++ / Re: Implementacion de una COLA en C, Error de ejecucion en: 14 Abril 2020, 16:42 pm
Dado que usas el operador de flecha con carro y tu código compila sin errores, ese miembro es un puntero, pero no estás reservando memoria para él. Haz eso y debería solucionarse tu problema.
134  Programación / Programación C/C++ / Re: Problemas con mostrar un registro en: 10 Abril 2020, 19:15 pm
Primero, algunas sugerencias/correciones. fflush(stdin) es incorrecto. La función fflush sólo se debe usar para flujos de salida, como stdout. Hacerlo con stdin es una violación a las reglas del propio lenguaje y aunque te pueda funcionar en Windows (en los otros sistemas operativos falla), no hay garantía de que siempre lo haga. En C++, una forma de limpiar el buffer es:
Código
  1. #include <limits>
  2. ...
  3. cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  4.  
O al estilo C, con while y getchar. Son básicamente las únicas maneras correctas de hacerlo. A veces recomiendan una con fseek, pero es tan incorrecta como fflush(stdin).
También deberías evitar gets. Es una función insegura y que desde hace años ya no es parte oficial de C o C++, y algunos compiladores incluso te darán error. En su lugar usa getline, cin.getline, o fgets.

En cuanto a tu problema, como ya te comentaron, es un error acceder a memoria que no reservaste. pun+1, pun+2, etc. apuntan a direcciones de memoria que no deberías tocar. Lo que sucede cuando lo haces es que estás escribiendo a direcciones que podrían estar ocupadas por otras variables (o que otras variables van a ocupar más adelante en la ejecución de tu programa), e incluso puedes ocasionar que tu programa se cierre inesperadamente, al estar accediendo a memoria que el sistema operativo no reservó para tu programa.

En tu caso, por lo que comentas, lo que debe estar pasando es que ptr+1 se refiere a la dirección de memoria ocupada por ne. Por lo tanto, cuando modificas ne, a la vez estás modificando un campo de ptr+1, y viceversa. Al usar la variable ju, evitas que tus gets modifiquen indirectamente a ne, pero al final de esa función, en la línea: ne = ju; al modificar ne, indirectamente estás modificando un campo de ptr+1, y de ahí los símbolos que mencionas. Por cierto, ju ni siquiera necesitaba ser const. Al ser variable local de capt, se encontrará en una posición de la memoria algo alejada de alu, que es variable global, por lo que no se superponen. Además, el calificador const sólo impide que en tu código manualmente modifiques la variable, pero todavía se puede modificar indirectamente si tienes un puntero a su dirección. De cualquier forma, el problema es que jamás debes acceder a memoria que no hayas reservado. Aunque algunas veces un programa que lo haga parezca funcionar correctamente, nunca es así. Internamente modifica algo que no debería y eventualmente causará problemas.
135  Programación / Programación C/C++ / Re: Funciones por referencia en: 9 Abril 2020, 20:33 pm
Lo de las funciones ya te lo respondieron, pero me parece necesario aclarar un punto. Y es que, si algún día te interesa meterte a nivel profesional a C++, los punteros son indispensables.

Es una pena que muchos autores se empeñen en meter a los estudiantes el miedo al manejo de memoria. Entiendo que quizás sea para que no se compliquen, pero me parece que hacen más daño que beneficio. Otra cosa sería si dijeran que no conviene usarlos sino hasta que uno tiene más experiencia, pero la mayoría de esos autores se limita a recomendar que nunca se usen, como como si a nivel profesional tampoco fueran muy necesarios, cosa que no podría estar más alejada de la realidad. Cualquiera que lleve un tiempo programando profesionalmente en este lenguaje se reirá ante la idea, y te dirá que la situación es totalmente la opuesta. Y es que es tan obvio y tan cierto como que 2+2=4 para cualquiera que esté metido en el tema, que no sé cómo esos autores pueden seguir publicando. De hecho, y por suerte, cualquier lector de estos libros que se llegue a dedicar profesionalmente a C++, se dará cuenta de lo importantes y útiles que son esos temas cuando llegue a la industria. El problema son los muchos estudiantes que luego se se pasarán a otros lenguajes, llevándose la idea de que esos temas, y la optimización en general, ya no importan porque las computadoras son "suficientemente rápidas". Y llegan al ámbito laboral sin saber hacer nada si no hay una biblioteca o framework que les dé todo masticadito, y de ahí la baja calidad y rendimiento de gran parte del software actual (pues en el mundo de Java, C# y, sobre todo, la programación web, estos temas les suelen interesar muy poco). Enseñarles a manejar correctamente la memoria a su debido tiempo, en lugar de crear un miedo irracional y ridículo, les daría habilidades muy importantes que después podrían aplicar aún en otros lenguajes.

C++ sin manejo de memoria no tiene prácticamente razón de ser. A la fecha, yo tengo casi 17 años de experiencia profesional (la mayoría de ellos programando en C++) y he conocido bastantes programadores del mundillo, y jamás he sabido de alguien que no use punteros en sus proyectos, incluyéndome. Seguro que alguno habrá, pero es rarísimo. Más aún, no conozco un sólo profesional de C++ que no considere el hecho de que este lenguaje permita usar punteros y acceder más o menos directamente a la memoria, como una de las mayores ventajas de programar en él. Salvo pocas excepciones, si no necesitamos manejar la memoria, no necesitamos (ni deberíamos usar) C++. Hoy ya casi ninguna aplicación "simple" (punto de venta, almacén, contabilidad, etc.) se hace en C++, y por buena razón. Hay lenguajes mucho más simples, productivos, y en general, más adecuados, como C#. C++ ha ido quedando relegado a proyectos donde se trabaje de cerca al hardware o donde se requieran grandes optimizaciones, y, obviamente, desde hace dos décadas no se pueden hacer optimizaciones significativas —salvo las más triviales— sin manejar manualmente la memoria. Es imposible. De hecho, según los requerimientos que se tengan, los propios new y delete (y malloc y free) predeterminados pueden ser de demasiado alto nivel para usarse. Por eso tampoco es raro que en su lugar se usen allocators propios y llamadas a las funciones nativas del sistema operativo para implementar un sistema personalizado de manejo de memoria. Porque tener un control preciso de cuándo y cómo se reserva y libera suele dar muchos beneficios. Según el caso, es perfectamente posible hacer que código crítico se ejecute 2, 3, 5 veces más rápido sin cambiar absolutamente nada del código, salvo las funciones de manejo de memoria. Y no es que estas cosas sólo se hagan en proyectos grandísimos de la NASA o similares. En la industria del videojuego, por ejemplo, esto es muy común, tanto en PC como consolas.

Resumiendo: al estar empezando, sí conviene mantenerte alejado de punteros y acceso "directo" a la memoria. Y si sólo te interesa programar como pasatiempo es perfectamente válido seguir así. Pero debes saber que, si tienes el interés de alguna vez dedicarte profesionalmente a programar en C++, manejarte con soltura en estos temas es indispensable. Estimaría que más o menos por cada 20 empleos de C++ donde vas a necesitar aplicar estos conocimientos, habrá con suerte uno donde no sea así. Y, si ya de por sí, hoy en día no hay tantos empleos en C++, pues, imagínate...

Si te interesa profundizar, además de libros, en youtube hay muchos videos de conferencias de C++. Muchas de ellas son dadas por personas que principalmente se dedican a escribir libros, dar charlas y "consultorías", por lo que, aunque suelen ser bastante correctas en cuanto a describir cómo funcionan las cosas (y con ese fin las recomiendo), yo me tormaría con muuuchas reservas sus consejos sobre buenos usos y prácticas. Para eso, limitarse a programadores de verdad, que programan día a día, y simplemente, en ocasiones dan charlas. Mike Acton es un buen ejemplo, aunque sus temas son más dirigidos a gente con nivel ya intermedio al menos.
136  Programación / Programación C/C++ / Re: Movimiento en un juego c++ en: 30 Marzo 2020, 04:53 am
En modo texto sólo es posible mostrar caracteres en su forma normal, y no se pueden girar. O usas alguna biblioteca gráfica, o lo simulas con caracteres distintos que den la ilusión de rotación. Por ejemplo: < ^ > v.
137  Programación / Programación C/C++ / Re: Se me cierra el socket. No veo el motivo. en: 30 Marzo 2020, 04:49 am
Hay algunos errores en tu código. El principal es esta línea:

Código
  1.    if (procesoHijo != ERROR) {

En el if anterior ya verificabas si hubo error, por lo que si llegamos hasta aquí, eso significa necesariamente que fork se ejecutó exitosamente, luego este if sobra, y de hecho, en este caso lo que hace es que la conexión se cierre siempre que no haya error, que es justo lo que está causando tu problema. Lo que siempre se debe hacer después de llamar a fork y comprobar que no falló, es verificar si estamos en el proceso hijo (fork devolvió 0) o en el padre, y actuar en consecuencia.

Tal como está el programa, sólo se acepta un mensaje por conexión, pero por lo que comentas al inicio, no sé si sea lo que quieres. Si no es así, no llames a exit sino hasta que se cumpla cierta condición, como recibir el mensaje "CLOSE".

Edito: porque veo que se me cruzaron dos ideas, y en lo que borraba para corregir, terminé diciendo algo a medias. Lo que quise decir es que el programa tal como está tendrá procesos zombis, porque no hay ningún wait, aunque realmente esto sólo representaría un problema si creas muchos procesos hijos.

Tu función callback no detectará correctamente errores, ya que write y read devuelven -1 cuando algo falló, pero tú estás verificando que devuelvan un valor menor a -1 (ERROR).
138  Programación / Programación Visual Basic / Re: Problema muy extraño con ShellEjecute en: 25 Marzo 2020, 17:02 pm
No sé si aún te sirva, pero es bastante obvio que algo sí que es diferente en ambos casos, y es un error muy común cuando uno tiene poca experiencia. Siempre que uses cuadros de diálogo para abrir o guardar archivos, ten presente que te pueden cambiar el directorio actual (working directory).

Puedes ver que eso está ocurriendo en tu programa. Fíjate en tu video, en las ventanas de consola, desde dónde se están ejecutando los comandos del bat. Seguro alguno de esos comandos depende de la ruta, y por eso el error.
139  Programación / Programación C/C++ / Re: Llamada al sistema Select en S.O Linux en: 10 Marzo 2020, 23:47 pm
El ejemplo específico de fallo del checksum al que se refieren en el link que pusiste sólo aplicaba para UDP, y hace tiempo fue corregido. Todavía podría presentarse ese problema, por causas distintas, pero no sé qué tan probable sea. Si esto sólo lo estás haciendo para practicar o aprender, perfectamente puedes usar select con sockets bloqueantes, pero ten en cuenta que para usos más serios, ignorar la posibilidad de error y simplemente suponer que casi nunca va a ocurrir es inaceptable, sobre todo cuando no es difícil hacerlo de otras formas, como con sockets no bloqueantes o, como ya te sugirieron, con epoll, que no tiene el problema de select.

Lo único que select hace es preguntar al kernel (enviándole una estructura, que el kernel rellena con información) si los descriptores de archivos especificados están listos. En este caso, "listo" significa que una operación de lectura/escritura no se bloquearía. En otras palabras, select simplemente informa si puedes leer o escribir en los archivos, sockets, etc. especificados sin que haya bloqueo. Que haya o no datos nuevos es algo que sólo sabemos intentando leerlos.

Cita de: SDCC
¿acaso se tiene la seguridad de que el kernel va ser capaz de quitar la información entrante erronea(que no cumplio con el checksum) antes de que la función recv recolecte los datos?

Sí. Una aplicación jamás debería leer datos que no pasen la verificación del checksum. Sólo una implementación defectuosa de TCP/IP permitiría algo así. Volviendo al problema inicial del link, lo que sucedía era que, al recibir datagramas, se ponían en la cola, y el checksum únicamente se verificaba en el momento en que una función como recv intentaba leerlos. En caso de fallo, los datos se descartaban y la operación de lectura se bloqueaba (en el caso llamada bloqueante), por lo que, aún en este caso, recv nunca recogería datos que no hubieran pasado el checksum.

En el ejemplo que pones al final, no sería necesario el sleep, ya que select se encarga de eso. En cuanto a asegurarte de recibir el número de bytes deseados, eso es algo que deberías hacer independientemente de si usas sockets bloqueantes o no bloqueantes. No hay garantía de que recv te dé la cantidad de información que le solicites. Incluso con el flag MSG_WAITALL, todavía hay circunstancias en las que podrías necesitar más de una llamada a recv para leer completo el bloque deseado, por lo que lo correcto sería que tu programa maneje esa posibilidad. Claro que, como te decía al principio, todo depende de lo que consideres aceptable en tu programa. Lo importarte es no engañarse creyendo que los errores poco probables no importan. Sí que importan. Simplemente en algunas circunstancias puede ser válido no manejarlos.
140  Programación / Programación C/C++ / Re: Ayuda con hilos en C en: 15 Febrero 2020, 18:40 pm
El problema es que execv(), como todas las funciones exec, crea un nuevo proceso que reemplaza al actual. Naturalmente, esto significa que cuando ejecutas execv(), el proceso original, con todos sus hilos, es finalizado, y lo único que queda ejecutándose es el comando.

Podrías crear un subproceso hijo (fork()), o bien, reemplazar el execv() por system(), pero el problema de fondo es estar invocando programas externos. Cualquier solución va a ser sucia y no óptima. Siempre es mucho mejor usar desde tu código alguna biblioteca para eso.

Si forzosamente quieres hacerlo con comandos, seguramente lo más sencillo sea que simplemente uses system() en lugar de execv(). En ese caso, deberías eliminar el while, o te será imposible cerrar el programa, a menos que mates el proceso. Fíjate si play acepta algún argumento para repetir indefinidamente el sonido, o escribe tú un script que lo haga, e invócalo desde system().
Páginas: 1 2 3 4 5 6 7 8 9 10 11 12 13 [14] 15 16 17 18 19 20 21 22 23 24
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines