miércoles, 4 de junio de 2025

Nueva forma de hacer un segmentation fault

        El segmentation fault,  segmentation violation, segfault, SIGSEGV o violación de acceso es la pesadilla de muchos, casi siempre causada por presencia de "undefined behaviour" (UB), lo primero que viene a la mente es punteros y memoria no asignada por ejemplo:

std::vector<int> *v;
v->push_back(5);

        Pero hoy les traigo una nueva forma de ocasionar un SIGSEGV sin usar punteros, memoria dinámica o malas practicas, con un objeto stack llamando a cualquier metodo va a generar un heap-buffer-overflow. Para esto vamos a crear una app con qml y C++ en Qt Creator. Después de tener el proyecto listo vamos a agregar una clase para el backend de nuestra app, esta solo tiene una función miembro que lo que hace es escribir a stderr, tiene un parámetro de tipo QVariantMap porque cuando pasas un objeto de javascript a C++ el runtime de qml lo convierte.

        En la función main vamos a crear una instancia de esa clase y hacerla accesible desde qml

        Como detonador vamos a crear una ventana con un botón, al hacer click se invoca la función con un objeto y es to inicia la reacción en cadena

        Ok, hasta aquí todo parece normal, todo es muy simple y no hay forma de que falle ¿Entonces donde esta el truco? ¡En las instrucciones de compilación! Este error lo encontre usando GCC (MinGW en windows), la biblioteca estandar incluida con GCC (libstdc++) tiene un modo debug, para activarlo hay que pasar un define al compilador: _GLIBCXX_DEBUG. Al activarlo g++ utiliza versiones debug de contenedores estandar que realizan mas verificaciones que lo normal, en la linea 7 se ve como se activa. 

        Tarde mucho en aislar el error porque tenia otros bugs y ya reparados parecia muy extraño ver un segfault en un objecto stack allocated, pero logre detectar lo que pasaba gracias al backtrace, pude ver que se estaba usando std::__debug::map en vez del regular, esto estaba causando un problema de incompatibilidad de ABI porque Qt6 esta compilado sin el modo debug y el memory layout es diferente y al querer accesar a los datos estos no estan el la misma direccion

        Para concluir surge esta pregunta: ¿Esto es UB? Se siguen todas las buenas practicas de C++ moderno en el proyecto y el código en si no tiene bugs, pero técnicamente si tiene UB porque al hacer el include el código de la biblioteca pasar a ser parte del programa, los contenedores de la biblioteca abstraen el manejo de memoria y aquí al acceder a una función a traves de una API no compatible se mostró el problema

El proyecto completo esta en mi github no olviden ponerle estrella

jueves, 29 de mayo de 2025

Compresion de videos

 Scripts con los argumentos para comprimir videos con ffmpeg



Aqui la version con compresion h265 que crea archivos mas perqueños pero tal vez sea menos compatible


jueves, 15 de mayo de 2025

Qt Creator se congela (Not responding) depurando un Segfault

 He estado desarrollando un app en windows usando Qt Creator, esta app usa ListView para mostrar datos y al hacer un cambio en el código introduje un bug de SEGFAULT a causa de usar un QList<QObjectDerived*> como modelo en vez de usar un QAbstractListModel debidamente creado para el propósito, pero lo que me pareció muy curioso(molesto) es que al después de ver el crash y volver a correr el programa con el debugger activo Qt Creator se congelaba. 

Parece ser un bug en la integración de Visual Studio, porque al usar GCC con GDB el funcionamiento es normal, el programa se detiene en el crash y se puede leer el Call Stack.

Mientras con el depurador de Microsoft solo aparece un dialogo con el texto:

Exception Triggered The inferior stopped because it triggered an exception.

 


Si alguien sabe otra solución por favor comentenla

martes, 8 de abril de 2025

Iconos gratis

 Aquí dejo una colección de links a sitios de iconos gratis

Imágenes de stock

Parece que todas las imágenes ya las puede generar la IA, pero seamos honestos: la mayoría de sus intentos de foto-realismo se ven horribles.  Aquí dejo una pequeña colección de links a imágenes de stock

martes, 1 de abril de 2025

no matching function for call to connect

Conectar un signal a un slot en Qt es tan simple como

connect(source,  &Source::Mysignal, destination, &Destination::slot);

Pero hoy recibi este error: No matching function for call to ‘MyClass::connect(QBluetoothDeviceDiscoveryAgent*&, , MyClass*, void (MyClass::*)(QBluetoothDeviceDiscoveryAgent::Error))’ 

En este caso el error es porque QBluetoothDeviceDiscoveryAgent tiene 2 miembros con el nombre "error", 

  • void QBluetoothDeviceDiscoveryAgent::error(QBluetoothDeviceDiscoveryAgent::Error error);
  • Error QBluetoothDeviceDiscoveryAgent::error() const;
Para desambiguar la llamada hay que usar un cast especificando la firma de tipado de la función

undefined reference to vtable for MyClass

 Normalmente cuando el compilador reporta el error "undefined reference to vtable for MyClass" es porque

  • Una funcion miembro sobrecargada no se marco como "virtual"
  • La funcion miembro sobrecargada no esta definida( no se ha implementado el cuerpo de la funcion)
Pero hoy encontre un caso diferente, mientras creaba una clase derivada de QObject para un servicio que usa QtBluetooth, ambos casos estaban cubiertos. El problema resulto ser que no estaba activo el MOC (Meta Object Compiler).
Para Arreglarlo solo hay que activarlo con una variable en el archivo 
CMakelists.txt



Debe ir antes del comando "add_executable"

martes, 18 de febrero de 2025

Error 15 (Lookup error.) en libmosquittopp

        He estado programando un app para monitorear una flotilla usando MQTT. Todo iba muy bien estaba programando en ubuntu 24 LTS y Qt Creator, pero a la hora de querer probarla en windows no se conectaba al broker, esto era muy raro ya que en Linux estaba funcionando perfectamente.

        Depurando encontre que mosqpp::mosquittopp::connect_async estaba retornando 15, un "Lookup error", en vez de cero que seria lo optimo, estuve googleando y no encontraba ningun caso igual, probe montones de cosas, como por ejemplo:

  • Compilar diferente version de mosquitto
  • Usar la distribucion binaria
  • Conectar a otros brokers
  • Usar la ip publica del broker directamente
  • Cambiar el DNS de windows
  • Cambiar la configuracion de red de Windows
        Despues empece a leer el codigo fuente de mosquitto y vi que el codigo de error MOSQ_ERR_EAI (15) era retornado mucho despues de fallar una llamada a getaddrinfo() entonces decidi poner una llamada a  getaddrinfo() para saber de que se trataba. 
        La invocacion de la funcion fallo pero dio un mensaje de error interesante: "Either the application has not called WSAStartup, or WSAStartup failed."
        Ya con esa informacion sospeche de la solucion correcta: algo no estaba inicializado y asi era hacia falta llamar mosqpp::lib_init(), asi que agregue al inicio del programa:

mosqpp::lib_init();
atexit([](){mosqpp::lib_cleanup();});