11 VirtualBox i CodeLite

11.1 Per què una màquina virtual?

La màquina virtual s’utilitza per tenir un entorn homogeni de programació, tant per part dels estudiants com per part dels consultors, de forma que qualsevol enunciat/solució publicat a les aules de teoria funcioni a tots els estudiants, i que tots els programes que realitzeu es comportin igual als entorns que s’utilitzaran per corregir-los.

Fa uns semestres ens vam trobar amb uns pocs casos en els quals un programa que funcionava correctament al PC d’un estudiant fallava a l’hora de ser corregit. I també alguns enunciats que en determinats sistemes operatius / versions de compiladors C tampoc funcionaven correctament. Per aquest motiu es va decidir utilitzar una màquina virtual.

Els professors no tenim forma de controlar que realment utilitzeu la FP20222 o bé un CodeLite instal·lat directament al vostre PC, però si no és així es pot donar alguna situació poc desitjable com les que he comentat.

11.2 VirtualBox: requeriments

Per poder utilitzar VirtualBox és necessari que es disposi d’accés a l’opció de virtualització. Si no és així, es poden obtenir errors del tipus: VT-X está deshabilitado en el BIOS para todos los CPUs.

L’error es pot produir per diverses raons:

  • La BIOS del PC té deshabilitada l’opció. Per solucionar-ho, cal entrar dins de la BIOS del PC i trobar l’opció d’activació de la virtualització (varia segons el fabricant): pot ser VT-x, Virtualization Technology, VT-x/AMD-V, Intel Virtual Technology, Tecnología de virtualización (VTx/VTd), etc.
  • Tenim actiu un antivirus que té activada una virtualització pròpia que entra en conflicte amb la requerida per VirtualBox. En aquest cas, únicament cal desactivar l’opció de virtualització de l’antivirus.

11.3 Com instal·lar les Guest Additions

Les Guest Additions són una sèrie de drivers que milloren la interacció entre host i màquina virtual. Per instal·lar-les únicament cal:

  1. Engegar la màquina virtual FP20222
  2. Anar a la barra de menú superior -> VirtualBox -> Devices -> Insert Guest Additions CD Image… -> instal·larà una unitat de CD amb les Guest Additions.
  3. Obrir un terminal des de Lubuntu -> System Tools -> LXTerminal.
  4. Dins del terminal LXTerminal executar el següent (la versió que s’estigui instal·lant pot ser més nova que la 6.0.12):
cd /media/uoc/VBox_GAs_6.0.12/     
sudo sh ./VBoxLinuxAdditions.run
  1. Reiniciar la FP20222 per activar les Guest Additions.

11.4 Primers passos amb CodeLite

A les xWiki trobareu el mòdul Introducció a l’entorn de programació CodeLite, en el qual es detallen els passos a realitzar per preparar l’entorn.

A continuació es resumeixen una sèrie d’aspectes que es comenten a la xWiki i que són importants recordar:

  • Un workspace de CodeLite és una agrupació de projectes.
  • Únicament es pot tenir un workspace obert dins de CodeLite.
  • Per crear un workspace: CodeLite -> Workspace -> New Workspace… -> Workspace type: C++ -> Workspace name: el que correspongui; Workspace Path: /home/uoc/Documents/codelite/workspaces/ (o qualsevol altre) -> fi.
  • Com que no es pot tenir més d’un workspace obert, no en podreu crear cap de nou si prèviament no tanqueu el workspace actiu. Si dins del menú de CodeLite veieu l’opció New Workspace en gris i que no es pot seleccionar, significa que ja teniu un workspace obert. Per tancar-lo: CodeLite -> Workspace -> Close Workspace.
  • Per afegir un projecte a un workspace: CodeLite -> File -> New -> New Project -> de tipus Console: Simple executable (gcc) -> Project name: el que correspongui -> Compiler: gnu gcc; Debugger: GNU gdb debugger -> fi.
  • El projecte que acabem de crear conté un programa hello world de mostra, que si executem mostra el missatge “hello world” per pantalla. Aquest programa en C el podem editar i afegir/treure tot allò que vulguem. És aquí dins on hem de codificar els nostres programes en C (no els algorismes!).
  • Si tenim més d’un projecte dins d’un workspace, la forma que tenim per indicar quin d’ells és el que està actiu és fent doble clic sobre el nom del projecte. Veureu que el nom queda remarcat en negreta i cursiva: a partir d’aquest moment, aquest serà el projecte que compilarem i executarem des de les opcions del menú de CodeLite. Tot i que estiguem visualitzant per pantalla el codi d’un altre projecte, la compilació i execució sempre es farà del projecte actiu.
  • Per mostrar la barra d’eines (icones) a la part superior: CodeLite -> View -> Show toolbar.
  • La icona del play de color verd cap a la dreta de la toolbar és el debuggar, i no serveix per compilar.
  • Per compilar i executar podem fer: CodeLite -> Build -> Build and run project. També es pot compilar amb la icona de la toolbar de la fletxa blanca avall amb fons verd, i executar amb la icona de les rodes dentades grises.
  • El resultat de l’execució del programa es mostrarà en una pantalla nova tipus terminal. És important anar tancant aquestes finestres una vegada ja hem comprovat el resultat de l’execució.

11.5 Com activar un projecte

Dins de CodeLite, a la part esquerra es mostren tots els projectes que s’han creat al workspace. Si ens fixem en el nom de tots ells, veurem que un està remarcat en negreta; per exemple podem tenir:

  • PAC01
  • PAC02
  • PAC03
  • PAC04

Això significa que quan anem a CodeLite –> Build –> Build and Run Project, s’executarà l’acció sobre el project PAC02, tot i que per pantalla s’estigui mostrant el codi d’un altre project.

Si es fa doble clic amb el ratolí sobre el nom del project PAC04, ara veurem:

  • PAC01
  • PAC02
  • PAC03
  • PAC04

A partir d’aquest moment, el Build and Run Project s’aplicarà sobre PAC04.

11.6 Canviar idioma del teclat

Per canviar l’idioma del teclat a Lubuntu, cal clicar amb el botó dret del ratolí sobre la barra grisa superior -> Add/Remove Panel Items -> pestanya Panel Applets -> botó Add -> seleccionar el plugin Keyboard Layout Handler -> Add -> Close.

En aquests moments a la part superior dreta es mostrarà l’idioma definit per defecte pel teclat -> marcar sobre la bandera amb el botó dret -> “Keyboard Layout Handler” settings -> desmarcar l’opció Keep system layout -> es pot afegir l’idioma que es vulgui des del botó Add; es pot prioritzar un idioma o l’altre posant-lo en primera posició a la llista. Una vegada s’hagi guardat la configuració desitjada, ja haurà canviat la disposició del teclat al nou idioma.

Si s’han deixat definits uns quants idiomes a la llista, cada vegada que marqueu sobre la bandera de la part superior dreta, farà un canvi a l’altre idioma de la llista.

11.7 Canviar el teclat associat a un idioma

Per un mateix idioma tenim la possibilitat de seleccionar múltiples teclats, i fer així que la màquina virtual i CodeLite funcionin correctament amb el nostre teclat. En cas que tinguem problemes amb el teclat, podem modificar-lo de la següent forma:

  1. Accedim a la icona Lubuntu de la part superior esquerra -> Preferences -> seleccionem Fcitx.
  2. A la part superior dreta es mostrarà la icona d’un teclat -> hi seleccionem l’opció Configure Current Input Method.
  3. Es mostrarà una nova pantalla: desmarquem l’opció Only show current language a la part inferior, i ja podrem escollir el teclat que coincideixi amb el que tinguem.

11.8 Programa per defecte en crear un projecte

Cada vegada que es crea un nou projecte a CodeLite, per defecte sempre conté el codi del programa hello world:

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("hello world\n");
    return 0;
}

Per tant, quan volem crear el nostre propi programa, només cal esborrar el programa que crea per defecte i començar a codificar el nostre programa nou.

Si malgrat tot no es vol que es mostri aquest codi cada vegada, podem modificar el codi per defecte associat als nous projectes:

  • Editar l’arxiu /usr/share/codelite/templates/projects/executable/main.cpp, que és el que es carrega per defecte en crear cada nou projecte.
  • Crear un nou template de CodeLite i utilitzar-lo en el moment de crear un nou projecte. La creació d’un nou template es fa a partir d’un projecte que tinguem -> botó dret sobre el nom del projecte -> Save as template....

11.9 Com fixar el kernel d’inici amb Lubuntu

Tot i ser una situació gens habitual, es pot donar el cas que Lubuntu només ens arrenqui en un determinat kernel per problemes amb determinades targetes gràfiques.

Tot i que el kernel sempre es pot seleccionar en el moment d’inici de Lubuntu, podem fixar quin és el que volem utilitzar malgrat que aquest no sigui el més nou de tots. Una possible opció és fer-ho amb l’aplicació Grub Customizer; per instal·lar-la fem:

sudo add-apt-repository ppa:danielrichter2007/grub-customizer

Ens identifiquem amb la password de l’usuari uoc.

A continuació, actualitzem la llista de packages de tots els repositoris:

sudo apt-get update
sudo apt-get install grub-customizer

En aquest punt haurem instal·lat Grub Customizer dins de la màquina virtual FP20222: aquest programa ens permetrà confirmar exactament què hi ha definit a l’arrencada grub de la màquina virtual. Per executar el programa: icona de Lubuntu —> System Tools —> Grub Customizer —> posar contrasenya uoc —> a la pestanya inicial List configuration es mostren tots els kernels de què disposa l’entorn en aquests moments.

És recomanable fer una còpia prèvia de les PAC/PR que puguem tenir dins de la FP20222 abans de canviar el kernel d’inici. Per canviar el kernel d’arrencada per defecte: Grub Customizer -> pestanya General Settings -> com a default entry, seleccionar el kernel que funciona correctament d’entre tots els disponibles. Una vegada escollit, es prem el botó Save de la part superior esquerra.

Per aplicar el canvi que s’acaba de desar a l’arrencada de Lubuntu cal obrir un terminal de Lubuntu des de System Tools -> LXTerminal, i des del terminal teclejar:

sudo update-grub

Una vegada hagi finalitzat el procés, cal realitzar un reboot de la FP20222 per tal que agafi ara per defecte el kernel escollit.

11.10 Kernel driver not installed (rc=-1908)

En cas que utilitzem el sistema operatiu macOS i obtinguem l’error de VirtualBox Kernel driver not installed (rc=-1908) ... VERR_VM_DRIVER_NOT_INSTALLED (-1908), el podem solucionar de la següent forma:

  1. Anar a la icona d’Apple, a la part superior esquerra -> Preferències del sistema -> Seguretat i privacitat -> pestanya General -> a la part inferior es mostrarà el missatge System software from developer Oracle America Inc. was blocked from loading -> prémer el botó Permetre.
  2. Si no es veu el missatge indicat al punt anterior, significa que han passat més de 30 minuts des de la primera vegada que ha donat l’error. En aquest cas cal desinstal·lar VirtualBox -> tornar-lo a instal·lar -> forçar novament l’error -> executar els passos indicats al punt anterior.

D’aquesta forma permetem que macOS pugui executar productes d’Oracle, entre els quals hi ha VirtualBox.

11.11 BUG: unable to handle kernel NULL pointer dereference at 00000004

S’ha detectat que el kernel més nou de la màquina virtual FP20222 té alguna incompatibilitat amb els processadors AMD Ryzen 5. Aquest fet provoca que el procés d’arranc quedi aturat, mostrant per pantalla l’error BUG: unable to handle kernel NULL pointer dereference at 00000004.

La solució passa per utilitzar una versió de kernel anterior. Els passos a seguir són:

  1. Aturarem completament la màquina virtual i la tornem a iniciar.
  2. A l’inici del tot, quan es mostri la pantalla negra d’arrancada de la màquina virtual, premem la tecla shift.
  3. Es mostrarà el menú d’arranc: entrem dins de l’opció Advanced options for ubuntu -> seleccionem el kernel més antic en mode normal, no pas en mode recovery.

Una vegada validat que podem iniciar correctament amb un kernel diferent, el podem fixar seguint les indicacions del punt Com fixar el kernel d’inici amb Lubuntu.

11.12 Debugging a CodeLite

La depuració (debugging) dels nostres programes ens permet detectar i corregir errors de programació, sobretot quan la seva mida comença a ser important. Serveix tant per detectar errors que fan que el nostre programa finalitzi abruptament, com errors en els càlculs que provoquen resultats incorrectes (els d’aquest segon cas costen més de detectar que no els primers).

El debugger de C, igual que el compilador, és un petit programa extern a CodeLite; això significa que si volguéssim instal·lar CodeLite al nostre PC, posteriorment caldria afegir un compilador i un debugger de C. La màquina virtual FP20222 ja el té instal·lat i configurat, amb el que ja el podem utilitzar.

El debugger és un petit programa que permet executar el nostre codi C i posar pauses puntuals dins d’ell. Aquestes pauses s’anomenen breakpoints, i el seu objectiu és aturar el programa en determinades línies del codi i poder observar així el valor que prenen les variables.

Farem unes proves bàsiques amb el debugger en el següent codi d’exemple:

#include <stdio.h>
#define MAX_ELEMENTS 5

int main(int argc, char **argv) {
    int vEnters[MAX_ELEMENTS];
    int i;

    printf("\n>> S'inicialitza el vector vEnters[] a 0's \n\n");
    for (i=0; i<MAX_ELEMENTS; i++) {
        vEnters[i] = 0;   /* Línia on volem afegir un breakpoint */
    }
}

Volem saber per cada iteració, quin valor va prenent la variable i i també la posició corresponent del vector vEnters.

Per afegir un breakpoint a la línia indicada amb un comentari, cal situar el cursor sobre la línia i seleccionar CodeLite -> Debugger -> Toggle breakpoint. Una vegada fet, al davant de tot de la línia es mostrarà una rodona vermella per indicar que conté un breakpoint.

Per començar a debuggar no utilitzarem el clàssic Build and Run Project: en el seu lloc hem d’escollir l’opció CodeLite -> Debugger -> Start/Continue Debugger -> Build and Debug.

El codi començarà a executar-se i s’aturarà a la línia que conté el breakpoint. A la part inferior de CodeLite es mostrarà la pantalla Debugger amb una sèrie de pestanyes: entrem dins de Locals i veurem una taula amb els valors que les variables del programa tenen en aquest punt, similar a la següent:

Name Value Type
i 0 int
vEnters [5] int[5]
        0 -1073743940 int
        1 4195915 int
        2 1 int
        3 -1073743940 int
        4 -1073743940 int

Per descongelar l’estat i fer una iteració més del bucle, premem el botó play verd de la barra d’eines de CodeLite, o seleccionem CodeLite -> Debugger -> Start/Continue Debugger. L’execució realitzarà una iteració del bucle i es tornarà a aturar, permetent revisar els nous valors que han pres les variables del programa:

Name Value Type
i 1 int
vEnters [5] int[5]
        0 0 int
        1 4195915 int
        2 1 int
        3 -1073743940 int
        4 -1073743940 int

Important: si en algun punt el programa necessita una resposta per part nostra (com pot ser introduir una dada des de teclat), l’haurem de posar igualment al terminal d’execució (pantalla negra habitual) que obre el debugger en segon pla.

Per sortir del debugger premem el botó stop vermell, o bé seleccionem CodeLite -> Debugger -> Stop debugger.

Aquest és l’ús bàsic del debugger, però permet fer més accions, com per exemple:

  • Una vegada estem aturats en un breakpoint, podem anar executant les següents línies de codi una a una, amb l’opció CodeLite -> Debugger -> Next.
  • Dins de Locals es pot veure el contingut que tenim en memòria. Ens caldrà saber abans l’adreça de memòria a partir de la qual volem mirar, però la podem obtenir fàcilment amb l’especificador de tipus %p.

11.13 Llibreria math.h

math.h és l’arxiu de capçalera de la llibreria estàndard del llenguatge C dissenyada per realitzar operacions matemàtiques bàsiques. La utilització d’aquesta llibreria queda fora de l’àmbit de l’assignatura, ja que no es demanaran operacions que únicament es puguin realitzar amb ella. De totes formes, si alguna vegada es vol utilitzar, cal executar prèviament uns passos concrets en funció de l’entorn:

  • CodeLite: fer clic amb el botó dret sobre el nom del projecte -> Settings… -> Linker -> dins de l’apartat Linker Options afegir: -lm.
  • Terminal: en cas de voler utilitzar la llibreria des d’un programa compilat i executat des de terminal, cal afegir el paràmetre -lm en el moment de generar l’executable: gcc nomPrograma.c -o nomPrograma -lm

D’aquesta forma ja es pot utilitzar la llibreria math.h:

#include <stdio.h>
#include <math.h>

int main(int argc, char **argv) {
    int numero;
    int resultat;
    
    numero = 49;
    resultat = sqrt(numero);
    printf("L'arrel quadrada de %d és %d\n", numero, resultat);
    return 0;
}

El resultat de l’execució serà:

L'arrel quadrada de 49 és 7

11.14 CodeLite: tabulador vs espais

A l’apartat 7. Identació del mòdul Guia d’estil de programació en C s’indica el següent:

“S’aconsella identar amb quatre espais per nivell. Evitar l’ús de tabuladors, configurar l’editor per a desactivar-los (la”desactivació" dels tabuladors consisteix en realitat a inserir espais en el seu lloc)."

Es pot configurar CodeLite perquè cada tabulador que afegim al nostre codi quedi substituit automàticament per 4 espais en blanc. Els passos a seguir són: CodeLite -> Settings -> Preferences -> Editor: Intentation -> desmarcar l’opció Use tabs in indentation i al camp Columns per tab character in document posar el valor 4.