gennaio 2005 - Posts
Pino, il nostro giovane programmatore, agli esordi della sua carriera fu contattato da una piccola software house per realizzare un sistema software.
Le specifiche non erano particolarmente esaustive, ma alcuni requisiti erano chiari fin da subito: applicazione Windows, ambiente distribuito su intranet, scalabilità, prestazioni, modularità. Insomma, le solite belle parole che lasciano ampio spazio all'interpretazione.
Pino si buttò sul lavoro con entusiasmo, e i motivi erano semplici: nonostante la sua esperienza fosse relativamente povera, aveva in gestione quasi completa un sistema abbastanza complesso. Questo gli permetteva di scegliere in maniera autonoma le soluzioni da applicare e le tecnologie da utilizzare. E allo stesso tempo aveva la possibilità di realizzare l'applicazione sulla base della propria analisi architetturale.
A pensarci non è mica poco !
In ambienti più strutturati spesso chi progetta non implementa, chi implementa non fa test e non ha una visione globale sul codice che sta sviluppando, chi fa test non ha mai nemmeno letto il listato completo della classe che verifica e via dicendo.
Pino, invece, era insieme progettista, sviluppatore e tester, con tutti i vantaggi e gli svantaggi che ne derivano.
Alla fine del lavoro, il risultato non era niente male.
L'applicazione era stratificata e modulare.
Il data tier, in particolare, era il "pezzo" che soddisfaceva Pino più di ogni altro.
Aveva seguito il manuale del bravo programmatore: utilizzo di stored procedure, indipendenza dal motore database, modalità di accesso ai dati disconnessa. Prestazioni niente male, a maggior ragione in condizioni di carico elevate.
Quindi, dal suo punto di vista, aveva realizzato il software migliore.
Alcuni giorni dopo la consegna del prodotto, il cellulare di Pino squillò con insistenza.
Immaginatevi il nostro giovane programmatore immerso nella vasca, cocktail e sigaretta, musica new age, in stato di completo relax, bruscamente riportato alla realtà da un trillo fastidioso.
Lo stavano chiamando dalla ditta che gli aveva commissionato il lavoro. Come rovinare una mattinata perfetta.
Pino andò in ufficio, già nervoso di suo, imbottigliato in mezzo al traffico e con lo stomaco sottosopra.
Il software non funzionava.
Erano state necessarie piccole modifiche, e la ditta aveva messo mano al programma di Pino nel tentativo di aggiungere una semplice funzionalità.
Pino ci mise poco ad individuare il problema: il funzionamento del data tier era stato frainteso, lo schema dei definizione degli oggetti non era corretto, il programma dava risultati sbagliati.
Mentre Pino illustrava il modo di correggere il problema, si ritrovò a descrivere la struttura del data tier.
"Allora, per aggiungere questo metodo occorre definire e implementare una stored procedure fatta così, definire uno schema XSD così è così, aggiungere questo parametro qui, modificare l'interfaccia grafica qui e qui, rebuild solution e via".
Nel mentre, gli arrivò una domanda: "Ma non era meglio fare un metodo che formatta la stringa con la query e la esegue direttamente ?".
Pino provò a spiegare i motivi per cui la soluzione proposta non era per niente migliore.
Ma era evidente che non stava convincendo nessuno.
Da una parte, vedeva i softwaristi un po' perplessi: non conoscevano a fondo le tecnologie che Pino aveva utilizzato ed erano un po' spaventati.
Dall'altra parte, i commerciali non avevano la minima idea di che differenza ci fosse tra un approccio e l'altro, ma temevano che l'architettura utilizzata da Pino fosse troppo complessa per le competenze interne: mettere le mani in un'applicazione che non si conosce è tanto più semplice quanto questa fa cose semplici in modo diretto e con pochi fronzoli.
Risultato: la ditta non era contenta perchè temeva di non riuscire a mantenere un prodotto sviluppato in modo troppo articolato.
Tornando a casa, imbottigliato nuovamente nel traffico, Pino era pensieroso.
La sua convinzione non era cambiata: aveva realizzato il software migliore.
Ma se l'avesse scritto un po' peggio, magari a quel punto era ancora nella vasca da bagno, con il terzo cocktail in mano.
Lo stomaco sarebbe stato sottosopra lo stesso, ma almeno per motivi legittimi ...
Riporto in questo post la risposta che ho ricevuto stamattina dal Google Team.
La mia richiesta era quella di avere integrazione fra Google Desktop e Google Deskbar: in pratica chiedevo di poter inserire i parametri della ricerca nella deskbar ed ottenere nel mini-viewer anche i risultati "locali", che è una delle caratteristiche che mi aveva fatto optare per MSN Desktop Search.
La funzionalità è già da ora disponibile, ma un po' ... nascosta.
Ecco come la si può attivare, fin da ora:
...
Please note that you can currently configure your
Deskbar to perform Google Desktop searches. To do this, please follow the
instructions below:
1. Perform a Google Desktop search for any keyword.
2. Copy the search URL from your browser's address bar.
3. Click on the arrow to the right of the binocular eyes on your Deskbar
and choose 'Options.'
4. Click on the 'Customized Searches' tab, and then click the 'Add'
button.
5. Choose a name and a shortcut for your search. Then paste your search
URL into the 'URL' text box.
6. Near the end of your search URL, you will see 'q=' followed by your
search query. Delete everything after the 'q=' and replace it with '{1}'
(no quotes).
7. Click 'OK.'
Google Desktop search will now appear in your Deskbar's search menu.
...
La risposta è arrivata in poche ore, quindi grazie della prontezza !
Uno dei modi per condividere gli handle degli oggetti kernel fra processi differenti è l'utilizzo del nome dell'oggetto in questione.
Questo, ovviamente, richiede che il creatore dell'oggetto (P1) specifichi un nome nella chiamata alla funzione di creazione.
Ad esempio, se il codice del processo P1 richiama la CreateMutex come segue:
::CreateMutex (pSA, FALSE, "MyMutex");
un processo P2 può utilizzare il nome MyMutex per ottenere un handle all'oggetto mutex appena creato.
E se P1 e P2 sono processi appartenenti a sessioni differenti ?
Ad esempio, cosa succede se P1 viene eseguito in una sessione terminal server e P2 in un'altra ?
Oppure, senza scomodare la versione server di Windows, cosa succede su XP eseguendo i due processi da due sessioni differenti, attive grazie a Fast User Switching ?
[Apro e chiudo una parentesi: ho da poco scoperto che la combinazione WindowsKey + L è uno shortcut alla funzionalità di cambio rapido utente. Comodo ...]
Qui entrano in gioco i namespace degli oggetti kernel.
Facendo precedere al nome dell'oggetto un qualificatore di namespace, il processo creatore può indicare a Windows di creare l'oggetto nello spazio nomi della propria sessione (Local/) o in uno spazio globale (Global/). Altrettanto può (o deve ?) fare il processo che vuole ottenere l'handle dell'oggetto per nome.
Questo può essere fonte di bug, a volte anche "lunghi" da individuare se non si pensa subito al contesto.
Ieri, infatti, ho perso una mezza mattinata per questo motivo.
Situazione: due servizi Win32 che condividono un Memory Mapped File.
Eseguendo entrambi in versione release e come servizi, tutto funziona.
Eseguendo uno in debug e l'altro come servizio, P2 non riesce a leggere il MMF creato da P1 (da .NET, l'errore è una Win32Exception, "File not Found").
Il fatto è che, per dislocazioni varie in ufficio, uso spesso una connessione RDP e lavoro su un server che sta in un'altra stanza.
P1, che è stato eseguito come servizio, crea l'oggetto senza specificare un qualificatore di namespace: in quanto servizio, per default viene utilizzato il namespace Global.
P2, eseguito in debug da una sessione attivata da remoto, specifica anch'esso un nome senza qualificazione: essendo però eseguito come applicazione standard e non come servizio (in debug, ovviamente, è quello che risulta più comodo), per default i nomi vengono considerati relativi al namespace Local.
Risultato: i nomi sono differenti, P2 non trova il file e va in errore.
Chiaramente eseguendo entrambe le applicazioni come servizio (quindi nella sessione di sistema) il problema non si verifica.
Anzi, il problema non si verifica nemmeno eseguendo una delle due applicazioni in debug, ma dalla sessione 0 (quella attivata dal login locale sulla stazione terminal): anche in questo caso, infatti, per default il namespace è Global.
Quante volte ho giustificato i bachi delle mie applicazioni con: "Strano, in debug funziona ..." ?
Beh, stavolta è successo esattamente il contrario !
Sto per partire per Reggio Emilia, dove domani mi aspetta una sorta di demo / test-prima-del-collaudo.
Le intenzioni della vigilia erano di partire non oltre le 3 di pomeriggio, arrivare con tutta calma, doccia, cena e nanna presto.
Sono le 7 e 3 quarti ... direi che abbiamo un po' sforato con i tempi !
N.d.A. Parto da Genova, da qui a Reggio sono circa 3 ore, cena e nebbia escluse.
Sgrunt ...
Ho letto con interesse
questo post di Marco Russo e i relativi commenti.
Sentendo parlare di portatili più o meno ... portatili, mi è venuta in mente la mia borsa.
La quale è così composta:
- Notebook di tipo desktop replacement (per la cronaca è un Fujitsu AMILO che ha quasi un anno di vita): 4 chili scarsi.
- Alimentatore del suddetto: credo che superi il kg, ma non l'ho mai messo sulla bilancia, occhio non vede ...
- Disco esterno (Lacie da 250 Gb): 900 grammi, ma ovviamente è alimentato esternamente quindi ne andranno aggiunti 2 o 300
- Mouse USB
- Fogli vari (che presi singolarmente hanno peso trascurabile, peccato che tanti trascurabili fanno mezzo chilo di trascurabile peso)
- Un paio di chiavi USB: poca roba.
- Cavi vari: ethernet dritto, ethernet girato, un paio di USB, cavo telefonico
- Spesso il caricabatteria del telefonino: il peso non lo so, ma arrivati a 7 chili anche pochi grammi fanno la differenza.
I miei, quando li vado a trovare (ovviamente con borsa a seguito come la coperta di Linus) mi guardano con aria sconsolata.
Secondo me si ricordano di quando andavo a scuola sommerso da uno zaino più grosso di me, giusto perchè quei simpaticoni dei prefessori avevano messo un compito di latino (con dizionario) ed un tema (idem) nella stessa mattinata.
Quando si dice il peso della cultura, ci si dimentica il peso della tecnologia !
Giusto per
smentirmi subito e dire che non ho proprio solo debuggato, ecco un link [FONTE:
questo post di Sam Gentile]
SIW è un tool che dà un bel colpo d'occhio su diverse informazioni di sistema.
E' carino perchè riunisce veramente tante informazioni, anche abbastanza diverse logicamente, ma tutte a portata di click.
Si passa dall'elenco dei file aperti (con tanto di informazioni su chi li ha aperti) all'elenco delle applicazioni avviate automaticamente alla partenza del sistema (e, anche qui, viene indicato chi è il "responsabile").
Non mancano i dati hardware, ovviamente ...
Ah, dimenticavo le ultime due chicche.
E' gratis (non nel senso di Kazaa, nel senso di gratis:-)).
E' composto da un solo eseguibile.
[UPDATE: 3 chicche! File->Convert->Bin to Cue, comodo per chi usa Daemon Tools è ha a che fare con file immagine BIN]
Va bene, ora vado a far da mangiare, che è sinonimo di "attacco il microonde".
Buona serata a tutti :-)
... non l'avevano inventata per riposare ?
Ho appena chiuso Visual Studio dopo una giornata di debug.
Ogni tanto penso che, tutto sommato, a fare i lavoratori dipendenti c'è anche qualche pregio (se poi un dipendente lavora anche da casa è un altro paio di maniche, diciamo che comunque di solito non è tenuto a farlo ... ma qui chiudo perchè si potrebbe aprire un discorso un po' troppo lungo e complicato).
Giornata mogia, comunque, qui a Genova.
Almeno uno si consola pensando che, anche ad uscire, non c'era sto sole che spacca le pietre :-(
Da alcuni mesi ci sono due nuovi esseri viventi in casa mia (le zanzare non le considero tali, altrimenti il numero sarebbe ben maggiore).
Dust e Pugsley: due belve scatenate che il veterinario sostiene siano gatti, ma io credo siano pantere in miniatura (uno è anche tutto nero !).
A parte giocare tutto il giorno (e la notte :-)) e farsi le unghie sui materassi perchè le tende sono troppo banali, credo abbiano un istinto informatico nascosto.
Alcuni giorni fa ho sprovvedutamente lasciato il computer incustodito.
Torno alla scrivania e li becco, tutti e due, a passeggiare con noncuranza sulla tastiera.
Non mi preoccupo più di tanto perchè non avevo applicazioni aperte.
Li prendo, li sgrido con poca enfasi, li butto giù e ... ora MyComputer si chiama 5o !
Spiegazione: era rimasto il focus sul'icona MyComputer sul desktop, credo abbiano premuto F2 con quelle zampine malefiche, decidendo di cambiare nome al link.
Mi sembra la spiegazione più probabile perchè:
- Non mi vengono in mente altri modi per cambiare nome ad un collegamento senza usare il mouse (che, nonostante il nome, continuano ad ignorare) o combinazioni di tasti difficilmente riproducibili per un gatto (tipo tasto windows equivalente al tasto destro del mouse - quello alla destra della barra spazio - frecce per spostarsi su "Rinomina")
- Visto che errare è umano, perseverare è felino. Li ho ribeccati a passeggiare tra la serie di tasti numerici e dei tasti funzione !
Ovviamente questo è un danno irrisorio rispetto a quelli che fanno in giro per la casa, ma mi sembrava curioso da raccontare.
Ieri, un po' eufemisticamente, affermavo di non avere avuto poi troppi problemi nel passare ad un utente non amministratore.
Manco a dirlo (saranno passate a dir tanto un ventina di ore) arrivano le prime smentite.
Build di una solution contentente progetti managed e non. Tra questi un paio di librerie COM.
Come azione di "post-build", Visual Studio registra i componenti COM appena compilati.
Immancabilmente la registrazione fallisce.
Per ora me la sono cavata con uno script che richiama regsvr32 da una shell "amministrativa", da utilizzare come post-build step.
Da un lato (ma questo è indipendente dal fatto di essere o meno amministratori della macchina) è opinabile che registrare i componenti COM come azione di post-build sia la scelta più corretta. Però in effetti è comodo: basta stare attenti al fatto che ad ogni build corrisponde una registrazione, e che questa inevitabilmente sovrascrive i settaggi precedenti.
Non so se è la soluzione migliore (ovviamente qualsiasi suggerimento è più che gradito [UPDATE: però se non abilito i commenti ...] :-)), ma raggiunge comunque il suo scopo ...
powered by IMHO
A quando un Pong.NET (sempre ammesso che non lo abbiano già scritto) ?
Mah ... Però voglio anche un mouse a forma di c1p8 ...
[Fonte:
questo post di Sean Campbell]
No no, niente di così radicale come un matrimonio o un cambio di lavoro ...
Però il 2005, tra le altre cose, mi ha convinto ad iniziare a utilizzare un utente a bassi privilegi (gruppo Users, per intendersi, niente più Administrators !) Motivo ?
Tanti consigli, da un lato.
Dall'altro, la necessità di sviluppare un applicazione utilizzabile anche da utenti che non sono amministratori della propria macchina.
In effetti, questa necessità dovrebbe essere tenuta in considerazione sempre, non solo quando c'è una richiesta esplicita a capitolato, fatto sta che mi sono deciso solo da pochi giorni.
Tutto sommato pensavo che sarebbe andata peggio ! (Di solito quando si dice così il peggio è lì dietro la porta che ti aspetta: l'hai invocato, mo' son cavoli tuoi :))
I problemi principali, come immaginavo, li ho avuti durante le installazioni.
I programmi scritti meglio avvisano ancor prima di iniziare la procedura di setup che non si hanno i privilegi sufficienti a proseguire.
Altri semplicemente rilevano l'errore durante l'installazione e abortiscono.
Le cause possono essere diverse, come il tentativo di accesso a directory "protette" o di scrittura in alcuni rami del registro di sistema.
Per fortuna che si trovano un sacco di informazioni e tool utili in giro per la rete !
In pratica viene lanciata una nuova shell dei comandi - cito testualmente - "running under your normal user account, but in a new logon session in which it is a member of the Administrators group". Ogni applicazione lanciata nel contesto della shell amministrativa girerà con i privilegi di amministratore, senza peraltro influenzare le applicazioni già in esecuzione o altre avviate dalla sessione principale.
Ed ecco che il primo workaround l'ho trovato !
Installo da amministratore (ma sempre dal mio utente principale, semplicemente promosso in via temporanea) et voila, il gioco è fatto.
O meglio, quasi ...
Poco fa, ennesimo programma da montare, ennesima richiesta di privilegi amministrativi, MakeMeAdmin e tutto ok.
Alla fine del setup, mi viene chiesto di riavviare il sistema per applicare le modifiche (già sentita questa frase ...).
Chiudo tutto, reboot, sigaretta (il mio PC ha tempi di avvio piuttosto prolungati), login e ... "Fallita la registrazione del componente Vattelapesca.ocx, installazione abortita".
Sgrunt !! Per registrare un componente COM bisogna scrivere nel registro, ora sono di nuovo un semplice "User" e non posso farlo.
E vabbè. Sono andato a spulciare RunOnce per vedere cosa avrebbe dovuto fare lo step finale del setup e ho eseguito il comando da shell amministrativa. Per ora funziona ...
La cosa interessante, in tutto questo, è che si imparano un sacco di cose.
Per esempio cosa viene ritenuto azione privilegiata e cosa è accessibile anche ad utenti "qualunque".
Così la prossima volta che mi viene in mente di scrivere i file di log in "C:\Program Files\La Mia Applicazione\Log" ci penso due volte ! Speriamo che finiscano presto i tempi del "maledizione, non ho i privilegi" ...
Le impressioni dei primi 5 minuti di utilizzo sono decisamente positive.
In particolare:
- E' leggero (occupa più o meno la stessa memoria di notepad, l'avvio dell'applicazione è praticamente immediato)
- Ha funzionalità di syntax highlighting
- Indica il tipo di formattazione (CR+LF, solo LF, solo CR) e permette di switchare agevolmente tra questi (comodo per aprire e visualizzare correttamente file di testo scritti per Unix e convertirli, se si desidera, nel formato CR+LF di Windows)
- Lo zoom: è banale (con notepad basta cambiare le dimensioni del font), ma è comodo richiamare questa funzionalità da un tasto della toolbar
- Tab Settings
- Line Numbers
- Brace Matching
- UI pulita e curata
- E' free e sono disponibili i sorgenti (questa non è un'impressione d'uso, ma mi sembra importante lo stesso :))
Insomma, come inizio non c'è male !
Passando davanti alla libreria di camera mia mi sono soffermato ad osservare i libri di informatica, meticolosamente allineati in ordine di argomento nei ripiani più alti (sono una persona abbastanza disordinata, ma la mia "bibliotechina" è un discorso a parte :)).
Da quattro anni a questa parte ne ho comprato un discreto numero (a spanne dovrebbero essere una trentina), e in effetti, a volerli mettere in ordine cronologico di acquisto, rispecchiano abbastanza fedelmente l'andamento dei miei interessi e dei miei impegni sul lavoro.
Mi ha colpito una cosa, in questa rapida rassegna.
I primi 6 o 7 libri sono traduzioni in italiano.
Gli ultimi (con alcune eccezioni, prima fra tutte: alcuni autori sono italiani !) sono tutti versioni originali inglesi.
I motivi, pensandoci, ci sono.
Innanzitutto, col passare del tempo e con l'aumentare dell'esperienza, mi sono trovato a ricercare volumi che semplicemente non sono stati tradotti, o comunque difficili da reperire in versione italiana. Non sto parlando di libri introvabili su argomenti ultra-avanzati: un esempio su tutti è Advanced .NET Remoting di Ingo Rammer, che avevo a suo tempo cercato senza fortuna in versione tradotta, salvo poi ripiegare sull'acquisto on-line via Amazon .
In secondo luogo, spesso i volumi in lingua originale acquistati via Internet costano meno delle relative versioni tradotte che possiamo trovare in libreria. A maggior ragione ora che il cambio euro-dollaro invoglia a fare compere oltre oceano.
Terzo, ma in realtà primo per importanza. Da un po' di tempo preferisco leggere la versione inglese di un testo "tecnico" piuttosto che la sua traduzione.
Non fraintendetemi: ci sono sicuramente traduzioni di ottima qualità. Il problema è il metro con cui si misura la qualità di una traduzione tecnica.
Il mio parere è che, molto spesso, una traduzione è tanto più valida quanto poco è completa.
Pochi giorni fa stavo rileggendo alcune pagine di un volume sui sistemi operativi, nel quale il termine inglese HANDLE viene tradotto con MANIGLIA. Ora, non metto in dubbio che in italiano "handle" significhi "maniglia". Semplicemente mi sembrava poco naturale parlare di "maniglia di un semaforo" ... allora perchè non dire che con tale maniglia i "fili" possono sincronizzare l'accesso ad una risorsa !?!! (filo = thread)
Non è questione di fare i fighi o tanto meno di essere esterofili.
Solo credo che lo scopo della lettura di un volume tecnico sia quello di apprendere. Ed ognuno deve ricercare il mezzo (anche la lingua) che gli facilita l'apprendimento.
Da un lato, non essendo la mia lingua madre, sicuramente leggere in inglese comporta un ulteriore livello di "filtro" (la traduzione) e mi rende meno immediato l'assorbimento delle nozioni. Dall'altro, pero, si fa fatica a ri-tradurre tutti i termini come "maniglia" nel loro corrispettivo originale !
Voi cosa ne pensate ?
powered by IMHO
Ho letto con interesse questo post di Andrea Boschin relativo alle dimensioni in memoria delle struct.
Trovo sicuramente valide le considerazioni di Andrea: un risparmio di 4 byte è nulla sul singolo elemento, ma può assumere proporzioni ben maggiori su collection ben .. nutrite.
Ciò che, a mio parere, è ancora più importante è che una scarsa attenzione al layout di una struct può determinare effetti ben peggiori che alcuni mega di memoria virtuale occupata.
Mi riferisco alle situazioni di interoperabilità con applicazioni non gestite.
Immaginate di dover accedere ad un'area di memoria non gestita tramite la seguente struttura:
struct MyStruct {
UInt16 wordValue;
UInt32 dwordValue;
}
La classe System.Runtime.InteropServices.Marshal offre diversi metodi statici che consentono l'interazione con un ambiente non gestito.
Tra questi ci viene in aiuto, nel nostro esempio, il metodo PtrToStructure, che accetta un IntPtr e un'istanza di Type (il tipo che vogliamo marshalare) e ritorna un Object "castabile" al nostro oggetto target.
Per copiare i dati dall'area non gestita a quella gestita, la classe Marshal va a controllare le dimensioni, in byte, del tipo destinazione, e tale numero di byte viene copiato all'interno dello heap gestito.
Nel nostro caso, quanti byte occupa la struttura MyStruct ?
6, senza ombra di dubbio ! Peccato che, per ragioni di padding (rimando nuovamente al post di Andrea e all'articolo su MSDN che Andrea linka), la struttura occupa 8 byte.
Inutile dire che le conseguenze non sono esattamente piacevoli.
Il primo consiglio, in situazioni del genere, è di esplicitare il layout di una struct tramite l'attributo System.Runtime.InteropServices.StructLayoutAttribute, specificando il tipo di layout esplicito.
In tal modo, la definizione di MyStruct diventa:
[StructLayout (LayoutKind.Explicit)]
struct MyStruct {
UInt16 wordValue;
UInt32 dwordValue;
}
Questo codice non compila, non ancora, per lo meno. Infatti, quando viene richiesto un layout esplicito per un tipo, occorre indicare al runtime gli offset dei singoli campi.
Niente di più facile.
Riscriviamo MyStruct:
[StructLayout (LayoutKind.Explicit)]
struct MyStruct {
[FieldOffset (0)]
UInt16 wordValue;
[FieldOffset (2)]
UInt32 dwordValue;
}
In questo modo, il campo dwordValue viene letto dalla posizione di memoria immediatamente contigua a wordValue, senza che vengano inseriti i 2 byte di padding.
Quindi, finalmente, MyStruct occupa .... 8 byte !
Ma come ?!?
Beh, in effetti non abbiamo fatto altro che "spostare" i due byte di padding in fondo alla struttura !
Se controlliamo le dimensioni di MyStruct (tramite Marshal.SizeOf (typeof (MyStruct))) il valore che ci viene ritornato è 8.
In un errore di questo tipo sono incappato alcuni mesi fa: dovevo accedere ad un MemoryMappedFile da un'applicazione .NET. Avevo a disposizione una classe a cui dovevo passare semplicemente l'offset di un dato a partire dal suo IntPtr di base.
La mia struttura (era un po' più lunga di MyStruct, ovviamente, ma poco cambia) affermava di essere grossa 124 byte (se non ricordo male), mentre in realtà i byte erano 123.
Dovendo accedere ad un array di strutture, non facevo altro che richiamare la funzione di accesso passando un valore intero, incrementato all'interno di un ciclo di Marshal.SizeOf(typeof (MyOtherStruct)) byte, cioè 124.
Verso la fine del ciclo, immancabile giungeva un'eccezione Win32: stavo leggendo dove non dovevo !
E allora ?
La soluzione è stata semplice: l'attributo StructLayout accetta un parametro Size, tramite il quale si può specificare la dimensione reale della struttura.
Impostato quello, tutto è filato liscio
... beh, sino al bug successivo, ma questa è un'altra storia !
powered by IMHO
More Posts
Next page »