[GIOCO MUSICA]
>> DAVID J. MALAN: Va bene.
Questo è CS50.
E questo è l'inizio della settimana 5.
E come avrete notato, parte del materiale
è sempre un po 'di più complesso, il poco più denso.
>> Ed è molto facile, soprattutto se sei stato l'abitudine per qualche tempo,
per cercare di scribacchiare più tutto quello che facciamo, stiamo dicendo in classe.
Ma si rendono conto, che non è forse l'approccio pedagogico ideale
per imparare questo tipo di materiale, e più in generale di materiale.
E così siamo lieti di annunciare proprio Gheng che di CS50
Gong ha iniziato a preparare un insieme canonico di note
per il corso, la speranza di cioè che, uno, questi
servire non solo come riferimento e una risorsa
per la revisione del materiale e andare indietro attraverso materiale che potrebbe avere
si sfuggiti la prima volta intorno, ma anche in modo che le vostre teste possono essere più
alto che verso il basso, quando arriva il momento di tenere una conferenza,
in modo che si potrebbe coinvolgere più pensieroso, come
al contrario di più Scribbly.
>> Detto questo, ciò che troverete su il sito è tali documenti come questo.
E notate, in alto a sinistra, c'è non solo un sommario,
ma anche i codici di tempo che provoca il salto immediato si
per la parte appropriata nel video online.
E che cosa Chang qui ha fatto è, in sostanza, documentata
quello che è successo in questo particolare lezione.
E molte delle lezioni sono già online con questo URL.
E noi continueremo a postare il resto di quelli per la fine di questa settimana,
in modo da trarre vantaggio da tale risorsa.
>> Quindi, senza ulteriori indugi, abbiamo iniziato a buccia indietro
lo strato che è stata stringa per qualche tempo.
E che cosa abbiamo detto una stringa in realtà è la settimana scorsa?
Stella Così char.
E char stella, bene, che cosa ha fatto che realmente significa?
Bene, tutto questo tempo, se abbiamo stato chiamare una funzione,
come getString, e la memorizzazione il cosiddetto ritorno
valore di getString in un variable-- si chiama
Tipo di s string-- abbiamo scriviamo la riga di codice lassù sopra.
Ed è solo quando vedo il mio scrittura a mano ingrandita qui
mi rendo conto di quanto questo è atroce.
>> Tuttavia, supponiamo che, sul lato destro
è, tuttavia, un ragionevole rappresentazione di ciò che è
sta succedendo tutto questo tempo con getString.
getString, naturalmente, ottiene una stringa.
Ma che cosa significa in realtà?
Significa che ottiene un pezzo di memoria dal sistema operativo
chiamando una funzione, chiamata malloc.
Ma ne riparleremo più avanti.
E poi popola che pezzo di memoria
con le lettere l'utente ha digitato, seguito da, ovviamente,
un carattere null, o backslash zero alla fine.
>> Nel frattempo, sul lato sinistro di questa storia, tutto questo tempo,
abbiamo dichiarazione di una variabile, come s.
E quello variabile è ciò che ora inizierà chiamare un puntatore.
Non è una scatola all'interno della quale abbiamo messo la corda, Daven, di per sé,
ma abbiamo messo in quella piazza casella sulla sinistra che cosa esattamente?
Sì?
>> PUBBLICO: L'indirizzo di dove si trova in memoria.
>> DAVID J. MALAN: Esattamente.
L'indirizzo di dove Daven si trova nella memoria.
E non dove tutti Daven si trova, di per sé, ma in particolare l'indirizzo
di che cosa?
Sì?
>> PUBBLICO: Primo carattere.
>> DAVID J. MALAN: Il primo carattere in Daven, che, in questo caso,
Ho proposto è stato arbitrariamente e irrealisticamente 1, OX1,
che significa semplicemente l' numero esadecimale di 1.
Ma è probabilmente andando essere un numero molto più grande
che potremmo trarre con un 0x come prefisso,
rappresenta un carattere esadecimale.
E perché non abbiamo bisogno di sapere dove il resto dei personaggi di Daven
sono, a causa di ciò che il design semplice decisione che è stata fatta molti anni fa?
Sì?
>> PUBBLICO: Barra rovesciata 0.
DAVID J. MALAN: Sì, esattamente.
Il backslash 0 consente, sia pure in tempo lineare, per attraversare la stringa,
a piedi da sinistra a destra, con un ciclo for, o un po '
loop, o qualcosa di simile che, e determinano, oh, qui
è la fine di questa stringa particolare.
Così, con solo l'indirizzo al l'inizio di una stringa,
possiamo accedere alla totalità delle , perché tutto questo tempo,
una stringa è appena stato una stella char.
>> Quindi è certamente bene a continuare a utilizzare la biblioteca CS50 e questa astrazione,
per così dire, ma ce la faremo cominciare a vedere esattamente
quello che sta succedendo sotto tutto questo tempo.
Così si può ricordare questo esempio, troppo, dall'ultima volta, confrontare 0,
che in realtà non confrontare.
Ma abbiamo cominciato a risolvere questo problema.
>> Ma, come forse un aggiornamento, potrei interessare a qualcuno
in un elefante rosa di oggi, fatta anche da Chang?
Come su di te di fronte? [Incomprensibile].
Andiamo su.
>> E nel frattempo, come si arriva, cerchiamo di
prendere in considerazione solo per un attimo che cosa questo codice è stato effettivamente facendo.
Si dichiara due variabili up top, s e t, e chiamando getString.
Questo non è un programma molto facile da usare, perché non ti dice cosa fare.
Ma facciamo solo supporre che siamo concentrandosi sulla parte succosa.
E allora che facciamo, se s è uguale a è uguale a t, si dovrebbe dire printf,
digitato la stessa cosa.
Ciao.
Come ti chiami?
>> Janelle: Janelle.
DAVID J. MALAN: Janelle, piacere di conoscerti.
Così il vostro sfida mano per questo elefante
è a noi disegnare prima un quadro di ciò che è essere rappresentati in quei primi due
linee.
Quindi s e t potrebbe essere rappresentata come sullo schermo?
E si può solo disegnare con il dito su questa grande schermo.
>> Quindi ci sono due metà di ogni lato di questa equazione.
Quindi c'è s a sinistra, e poi getString sulla destra.
E poi c'è t sulla sinistra, e poi getString sulla destra.
Così come potremmo cominciare un disegno che
rappresenta ciò che sta succedendo qui in memoria, diresti?
E lascia che ti permettono di spiegare quello che stai facendo, come si va.
>> Janelle: OK.
Beh, in primo luogo, sarebbe chiedere di ottenere la stringa di input.
E sarebbe store-- oh, mi dispiace.
DAVID J. MALAN: OK.
Buona.
E questo si chiama cosa?
Oh, OK.
Andare avanti.
Non volevo interrompere.
Janelle: Mi dispiace.
Quindi sarebbe in ingresso in l'indirizzo non di-- sicuro.
Non ricordo esattamente il numero, ma credo che stava iniziando con 0.
>> DAVID J. MALAN: Questo è tutto giusto, perché ho fatto i numeri in su,
quindi non c'è una risposta giusta.
>> Janelle: A partire dal 0 arco.
>> DAVID J. MALAN: OK, così elemento 0.
Certo.
>> Janelle: E allora se è stato come solo un due letter--
>> DAVID J. MALAN: OK, di nuovo voi.
>> Janelle: Così elemento 0, e quindi elemento 1 o elemento 2.
DAVID J. MALAN: E quale parte di l'immagine stai disegnando in questo momento?
La chiamata a getString?
O la dichiarazione di s?
>> Janelle: La dichiarazione di s, credo.
Oh, la getString, perché sarebbe essere immessi in ciascuna [? zona. ?]
>> DAVID J. MALAN: Good.
Esattamente.
Anche se questo in modo efficace restituisce una matrice, richiamo,
quando torniamo una stringa, possiamo indice in quella stringa con 01 e 2.
Tecnicamente, questi sono probabilmente rappresentata da singoli indirizzi,
ma va bene.
>> Quindi supponiamo, se posso solo veloce inoltrare a dove avevamo interrotto
ultima volta, se uno dei le corde erano g a b e,
backslash 0, rappresentando in tal modo Gabe ingresso, come potremmo rappresentare s adesso?
Se questa è la memoria che è stato restituito da getString?
>> Janelle: Sarebbe rappresentato da un arco?
>> DAVID J. MALAN: da un arco?
Beh, no.
Diciamo solo che, pittoricamente, vorrei solo andare avanti
e proporre che, se questo è s, questo è il valore di ritorno di getString.
E che hai disegnato questo come 0, 1, 2, che è perfettamente ragionevole, perché noi
in grado di indicizzare nella stringa, in quanto tale.
Ma solo per essere coerenti con l'ultima volta, lasciami andare avanti
e arbitrariamente proporre che questo è l'indirizzo 1, questo è l'indirizzo 2,
questo è l'indirizzo 3, e così via.
E così, giusto per essere super chiaro, che cosa sta succedendo
andare in s come risultato di tale prima riga di codice, diresti?
>> Janelle: Indirizzo 1?
>> DAVID J. MALAN: Esattamente.
So Indirizzo 0x1.
E intanto, lasciami andare avanti e duplicare gran parte di quello che hai fatto
e aggiungere la mia t qui.
Se dovessi digitare Gabe di nuovo, una seconda volta,
quando richiesto con getString, dove, naturalmente, è Gabe sta per andare?
Beh, presumably--
>> Janelle: Ti piace qui?
DAVID J. MALAN: Già.
Janelle: O è anche nelle stesse scatole?
DAVID J. MALAN: Fammi propongo, sì, esattamente, così in queste caselle aggiuntive.
Ma ciò che è fondamentale ora è che, anche se ho disegnato questi abbastanza vicino
together-- 0x1, questo è 0x2-- in realtà,
questo ora potrebbe essere l'indirizzo 0x10, per esempio, e 0x11, 0x12 e,
e così via.
E così, se questo è il caso, quello che sta andando a finire qui in t?
>> Janelle: 0x10?
DAVID J. MALAN: Esattamente.
Così 0x10.
E così ora, ultima domanda.
Lei ha, di gran lunga, ha dovuto lavorare il più difficile per un elefante finora.
A questo punto, se mi tiro su il codice ancora una volta, quando lo faccio, in linea tre,
se s è uguale uguale a t, che cosa sono in realtà confrontando che abbiamo disegnato qui?
>> Janelle: I due indirizzi?
DAVID J. MALAN: Esattamente.
Così sto dicendo è s uguale uguale a t?
In altre parole, è 1 uguale uguale a 10?
E, naturalmente, il risposta ovvia è ora, no.
E quindi questo programma è in ultima analisi andando a stampare ciò, diresti?
>> Janelle: Sarebbe, digitato la stessa cosa?
>> DAVID J. MALAN: Quindi, se s è 1 e t è di 10?
>> Janelle: È stato digitato cose diverse.
>> DAVID J. MALAN: Esattamente.
È stato digitato cose diverse.
Bene.
Quindi un applauso, se potessimo, qui.
[Applausi]
E 'stato doloroso.
Lo so.
Ben fatto.
Così ora vediamo se non possiamo prendere in giro a parte ciò che la correzione era.
E, naturalmente, quando abbiamo fissato questo-- che io oggi rappresento in green--
abbiamo fatto un paio di miglioramenti qui.
In primo luogo, proprio come un sanity controllare, sto controllando prima
se s è uguale a nulla e t è uguale a null.
E tanto per essere chiari, quando potrebbe s o t essere null in codice come questo?
Quando potrebbero s o t essere nullo.
Sì?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Esattamente.
Se la stringa che l'utente digitato è troppo lungo
per adattarsi in memoria, o qualche angolo strano caso del genere,
getString, come vedremo, letteralmente oggi, nella sua documentazione,
dice che restituirà null come un valore sentinella speciale,
o semplicemente una sorta di simbolo speciale questo significa che qualcosa è andato storto.
Quindi vogliamo controllare che, perché si scopre
che null è un valore molto pericoloso.
>> Spesso, se si tenta di fare qualcosa con nulla che coinvolge un function-- passandola
come input, per instance-- quella funzione potrebbe molto in crash e, con esso,
prendere giù tutto il programma.
Quindi questa terza linea ora è solo una sanità mentale controllare, controllo degli errori, se si vuole.
Questa è una buona abitudine ora ci si trova in ogni volta che
tentare di utilizzare un valore che potrebbe, potenzialmente, essere nullo.
>> Ora, nella quarta linea qui, "Se strcmp (s, t)," bene,
cosa c'è che riferisce?
Beh, abbiamo detto che questo era un modo molto succinto funzione denominata per il confronto tra stringhe.
E il suo scopo nella vita è quello di confrontare il suo primo argomento contro di essa secondo,
ma non in termini di indirizzi, come abbiamo fatto involontariamente un momento
fa con il codice rosso, ma piuttosto per confrontare quei due
stringhe nel umanamente intuitiva modo confrontando questo, contro questo,
contro questo, contro questo, e poi fermarsi se e quando uno
o entrambe le mie dita colpisce una barra rovesciata 0.
Strcmp Così qualcuno anni fa, attuate di attuare per noi la funzionalità
che speravamo avremmo ottenuto semplicemente confrontando due valori semplici.
>> Ora, francamente, io continuo il disegno tutti questi diversi numeri.
Ma la realtà è, sono stato rendendo questi su tutto il tempo.
E così vorrei solo andare avanti e scarabocchiare questi fuori
per fare un punto che, alla fine del giorno e andare avanti,
non stiamo davvero andando a cura di quali affronta le cose sono in realtà
in memoria.
Quindi io non ho intenzione di disegnare questi tipi di numeri tanto più,
Sono solo un abstract questa via un po 'più amichevole con solo le frecce.
>> In altre parole, se s è un puntatore, bene, facciamo solo disegnare esso, letteralmente,
come un puntatore, una freccia rivolta da se stessa a qualcos'altro,
e non preoccuparsi troppo di più la minuzia di questi indirizzi
che, ancora una volta, ho fatto lo stesso.
Ma staremo a vedere quegli indirizzi, a volte, durante il debug del codice.
>> Ora, nel frattempo, il programma qui correzioni, naturalmente,
che problema confrontando queste due stringhe.
Ma abbiamo incontrato un altro problema.
Questo è stato dalla copia programmare l'ultima volta,
in base al quale, stavo cercando di capitalizzare solo il primo carattere di una stringa.
Ma quello che era il sintomo abbiamo visto l'ultima volta in cui
un utente digitato un valore, come Gabe in minuscolo, per s,
poi abbiamo assegnato s in t, come nella terza riga lì,
e poi ho cercato di capitalizzare t Staffa 0?
Qual è stato l'effetto di cambiando t Staffa 0 qui?
>> PUBBLICO: E 'cambiato s.
>> DAVID J. MALAN: Sì, Ho cambiato s, pure.
Perché quello che stava realmente accadendo?
Beh, fammi vedere se riesco a pulire questa immagine, come segue.
>> Se s è, ancora una volta, la parola g, a, b, e, backslash, 0, e s
continueremo disegno come una scatola qui, ma non di più indirizzi.
Smettiamola di fare le cose.
Diciamo solo tracciare un quadro di semplificare il mondo.
>> Quando Dichiaro t con stringa t, che crea quel pezzo di memoria.
Piazza capita di essere 32 bit nella maggior parte dei computer.
Infatti, se hai mai sentito parlare di un computer con un'architettura a 32 bit,
davvero fantasia-parlare, che appena significa che utilizza indirizzi a 32 bit.
E come un tecnico a parte, Se vi siete mai chiesti
perché i computer più vecchi, se effettivamente cercato di zuppa in su con un sacco di RAM,
potrebbe avere solo un massimo di quattro gigabyte di RAM,
bene è perché, letteralmente, il vostro vecchio computer poteva solo
Numero alto come 4 miliardi, 4 miliardi di byte,
perché stava usando 32 bit numeri per gli indirizzi.
>> Ma in ogni caso, in questa esempio, di storia molto più semplice.
t è solo un altro puntatore, o davvero una stella char, aka stringa.
E come voglio aggiornare questa immagine ora con quella seconda riga di codice,
dopo il punto, dot, dot?
Quando faccio stringa t è uguale a s punto e virgola, Come cambia questa immagine?
Sì?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Già.
Esattamente.
Ho appena messo una freccia dalla t casella allo stesso indirizzo,
la stessa prima lettera ha dato.
Oppure tecnicamente, se questa ragazzo erano ancora in 0x1,
E 'come se avessi 0x1 0x1 qui e qui.
Ma ancora una volta, chi se ne frega riguardo gli indirizzi?
E 'solo l'idea che conta ora.
Quindi questo è quello che sta succedendo qui.
Così, naturalmente, se si fa staffa t 0, che è la notazione di matrice,
naturalmente-- e francamente, sembra come se ci fosse un array qui,
ma ora c'è questa cosa strana.
Sappiate che il linguaggio di programmazione, C, vi offre questa funzione,
per cui, anche se t è un puntatore oppure s è un puntatore,
è comunque possibile utilizzare quella familiare, confortevole parentesi quadra
notazione per passare al primo elemento, o il secondo elemento, o qualsiasi elemento
che tale puntatore punta a causa, presumibilmente, essa
è, come in questo caso, punta a un certo array.
>> Quindi, come possiamo risolvere questo problema?
Francamente, questo è dove ha ottenuto un poco travolgente a prima vista.
Ma qui è una versione nuova e migliorata.
>> Quindi, prima, mi sto liberarsi della biblioteca CS50,
solo per esporre che s è infatti una stella char, solo un sinonimo.
E t è anche una stella char.
Ma ciò che sta accadendo sul destra di tale linea
dove t è assegnato un valore?
>> Che cosa è malloc?
Che cosa è strlen?
Che cosa è sizeof (char)?
Perché diavolo fa questo linea sguardo così complesso?
Che cosa ci fa ad alto livello?
Che cosa è la memorizzazione in t?
Sì?
PUBBLICO: E 'assegnazione di un certa quantità di spazio di memoria.
E 'per memorizzare, immagino, lettere [incomprensibile].
>> DAVID J. MALAN: Perfetto.
Perfetto.
E 'assegnazione di un certo quantità di spazio di memoria
per memorizzare, presumibilmente, lettere futuri.
E in particolare, malloc è quindi tornando cosa?
>> PUBBLICO: Restituzione del [incomprensibile]?
DAVID J. MALAN: Esattamente.
Tornando l'indirizzo di tale memoria, che è un modo elegante per dire,
restituisce l'indirizzo del primo byte di quella memoria.
L'onere è su di me per ricordare quanta memoria ho effettivamente
assegnati o chiesto malloc per.
>> Ora, quanto costa?
Beh, anche se non c'è un sacco di parentesi qui,
malloc vuole solo un singolo argomento.
E sto specificando strlen di s, in modo da dare me tanti byte come ci sono in s,
ma aggiungerne uno.
Perché?
Sì?
>> PUBBLICO: Il backslash 0.
DAVID J. MALAN: Esattamente.
Dobbiamo fare un po 'di pulizia.
Quindi, perché c'è una barra rovesciata 0, faremmo meglio a ricordare che.
Altrimenti, stiamo andando per creare una stringa che
non ha che terminatore speciale.
>> Nel frattempo, giusto per essere super anale, ho sizeof (char),
nel caso in cui qualcuno corre il mio codice non sull'apparecchio CS50,
ma forse un altro computer complessivamente cui caratteri
sono un byte, per convenzione, ma due byte, o qualcosa di più grande di quello.
E 'solo di essere super, Super contrari a errori.
Anche se, in realtà, è molto probabilmente sarà un 1.
>> Ora, intanto, vado avanti e copiare la stringa, staffa t i è uguale a staffa t s.
E io rinviare alla settimana scorsa codice sorgente per vedere cosa sta succedendo.
Ma il takeaway chiave, e la motivo per cui ho messo il codice ora in verde,
è dovuto al fatto che molto ultima riga, t Staffa 0 è uguale toupper,
ha l'effetto di Capitalizzazione che stringa?
t e / o s?
L'ultima riga di codice.
>> Proprio t, perché ciò che è successo questa volta,
se mi sciolgo un po 'che ultimo passo, ciò che è accaduto è, quando chiamo malloc,
Ho in sostanza ottenere un pezzo di memoria che è lo stesso formato dell'originale,
perché questo è il aritmetica che ho fatto.
Sto memorizzazione in t l'indirizzo di quel pezzo di memoria.
Anche se questo sembra bello e carina, bella e vuota,
la realtà è che c'è, quello che faremo continuare ad invocare, i valori della spazzatura in qui.
Quel pezzo di memoria potrebbe molto pure sono state utilizzate prima,
pochi secondi, pochi minuti fa.
Quindi ci potrebbe assolutamente essere numeri o lettere lì, solo per caso.
Ma non sono valide, fino a quando ho Mi popolano questo pezzo di memoria
con caratteri reali, come ho fare in quel ciclo for lì.
Bene?
>> Così ora, il culmine di questi tre esempi
che sono stati apparentemente rotto l'ultima volta, questo esempio Swap, questa funzione
lavorato in senso che cambiasse ae b.
Ma non ha funzionato in quale altro senso?
Sì?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Esattamente.
Se dovessi chiamare questa funzione da another-- per esempio,
da una funzione come principale, dove Ho una variabile, x e y, come ho
ha fatto la scorsa settimana, stesso codice, e passo in x e y
di Swap, e quindi chiamare Swap-- questo, naturalmente, è la versione corretta
è quello che stiamo per see-- non ha funzionato.
Allora, qual è la soluzione?
>> Bene, così giusto per essere chiaro, lasciami andare avanti
e- dammi uno secondo qui, e vedere se posso mostrarvi l'ultimo, che
sarà dentro-- vediamo se riesco a trovare questo vero e proprio OK fast--, [incomprensibile].
OK, ci è.
Quindi ignorare i comandi Sto solo battitura.
Voglio che recuperare a all'ultimo minuto un esempio
dall'ultima volta, che ora è chiamato non Swap.
>> Quindi non Swap è dove avevamo lasciato l'ultima volta,
per cui, ho inizializzato x 1 e y 2.
Ho poi chiamo Swap, passando in 1 e 2.
E allora questa funzione lavorato in un certo senso,
ma non aveva permanente effettuare su xe y.
Quindi la domanda è a portata di mano, come ora possiamo effettivamente risolvere questo problema?
Qual è la soluzione a portata di mano?
>> Beh, in swap.c, che è nuovo oggi, notare un paio di differenze.
xey sono uguali.
Ma ciò che è chiaramente diverso in linea 25?
Cosa c'è di nuovo lì, se vi ricordate quello che sembrava un secondo fa?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Già.
Così i ampersands sono un nuovo pezzo di sintassi non solo in questo programma,
ma anche più in generale in CS50.
Fino ad oggi, non credo abbiamo visto esempi
o realmente parlato di loro in qualsiasi particolare, diverso, forse, preventivamente
in sezione, una e commerciale come questo.
Beh, si scopre e commerciale è una degli ultimi pezzi della nuova sintassi
stiamo andando a imparare.
Tutto ciò significa l' indirizzo di una variabile.
A quale indirizzo non x vivere?
Ma che cosa vuol indirizzo y vive?
Perché se il problema fondamentale prima
era che x e y si ripercuotono come copie, ciò che realmente vogliamo fare
è fornire Swap con come un tesoro mappa che conduce dove xey effettivamente
sono in RAM, in modo che Swap può seguire quella mappa
e andare ovunque x o y segna il punto e cambiare i valori effettivi 1 e 2
Là.
>> Quindi Swap bisogno di cambiare un po 'troppo.
E a prima vista, questo potrebbe sembrare un po 'simile a char stella.
E in effetti lo è.
Quindi, a è un puntatore a quale tipo di dati, sulla base di questa porzione evidenziata?
Quindi è un int.
>> Quindi una non è più un int, è l'indirizzo di un int.
E allo stesso modo, b sta ora per essere l'indirizzo di un int.
Così, quando ho adesso chiamo Swap da Main, Non ho intenzione di dare Swap 1 e 2.
Ho intenzione di dare come Ox-qualcosa e Ox-qualcosa,
due indirizzi che porteranno Swap nelle loro posizioni attuali
nella memoria del mio computer.
>> Così ora, la mia implementazione rimanente ha bisogno di cambiare un po '.
Che cosa è ovviamente diverso ora in queste tre righe di codice?
Ci sono questi maledetti stelle tutti sul posto, tutto a posto?
Così che cosa sta succedendo qui?
Sì?
>> PUBBLICO: E 'ovviamente [incomprensibile].
>> DAVID J. MALAN: Esattamente.
Quindi in questo context-- e questo non era la decisione migliore progettazione, è vero,
anni fa.
In questo contesto, dove hai solo una stella,
e non si dispone di un tipo di dati, come int, subito a sinistra,
invece si dispone di un segno di uguale, chiaramente, in questo contesto, quando si dice una stella,
questo significa andare al indirizzo che è in una.
Segui la mappa del tesoro, per così dire.
>> E intanto, in linea 37, significa la stessa cosa.
Vai all'indirizzo di una, e mettere quello che c'è?
Qualunque sia al posizione che b specifica.
In altre parole, andare a b.
Prendi quel valore.
Vai a una e, per la parità di firmare, l'operatore di assegnazione,
mettere quel valore lì.
>> Allo stesso modo, int temp è solo un int.
Nulla deve cambiare di temperatura.
E 'solo un bicchiere di riserva da Annenberg per un po 'di latte o succo d'arancia.
Ma ho bisogno di dire, andare a b.
Vai a tale destinazione e mettere il valore di temperatura lì.
Così che cosa sta succedendo allora?
Quando ho effettivamente Inverti chiamata questa volta, se questo primo cassetto qui rappresenta il principale,
questo secondo vassoio rappresenta Swap, quando Passo ampersand x e y e commerciale
da principale a Swap, tanto per essere chiari, che cosa è questo stack telaio di ricezione?
Sì?
>> PUBBLICO: [incomprensibile].
DAVID J. MALAN: Esattamente.
L'indirizzo della x e l'indirizzo di y.
E si può pensare di questi come indirizzi postali.
33 Oxford Street e 35 Oxford Street, e si
desidera spostare i due edifici che sono in quei luoghi.
>> E 'una sorta di un'idea ridicola, ma è tutto quello che noi intendiamo per indirizzo.
Dove nel mondo può a trovare quei due interi?
Dove nel mondo si può trovare quei due edifici?
Quindi, se finalmente, dopo tutto questo tempo mi andare in codice sorgente di oggi e compilare
Swap ed eseguire ./swap, infine, per il prima volta che facciamo in realtà vediamo che
i miei valori sono infatti stato scambiato con successo.
E ora, possiamo anche prendere nota di questo, per esempio, gdb.
>> Quindi lasciami andare nello stesso file.
Lasciami andare avanti ed eseguire gdb di ./swap.
E ora, in Swap, ho intenzione di andare avanti e impostare un punto di interruzione nel principale.
E ora ho intenzione di andare avanti ed eseguire il programma.
E ora vediamo il mio codice pausa a quella linea.
>> Se vado avanti e stampa x, che cosa dovrei vedere qui?
E 'una domanda.
Dire di nuovo?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Così numeri casuali, forse.
Forse sono fortunato, ed è bello e semplice, come 0.
Ma forse è un po 'di numeri casuali.
In questo caso, ho avuto fortuna.
Succede solo per essere 0.
Ma è davvero fortuna, perché non fino a quando ho
tipo successivo e poi stampare x ha che riga di codice, linea 19, stato giustiziato.
>> Nel frattempo, se digito il prossimo di nuovo, e ora stampare y, vado a vedere 2.
Ora, se digito il prossimo, sta andando a ottenere un po 'di confusione, perché ora,
printf sta per apparire su lo schermo, come ha fatto. x è 1.
>> Facciamolo di nuovo.
Ed ora, ecco dove le cose si fanno interessanti.
Prima che io chiamo Swap o addirittura passo in esso, diamo un po 'un'occhiata.
x è, ancora una volta, 1.
Y è, naturalmente, sanità mentale rapido controllare, 2, quindi non è difficile là.
Ma ciò che è commerciale x?
Risposta, è una specie di funky cerchi.
Ma l'int stella tra parentesi è solo modo di gdp di dire questo è un indirizzo.
Non è un int, è un puntatore ad un int, o altrimenti conosciuto come un indirizzo.
>> Che cosa è questa cosa pazzesca?
Non abbiamo mai visto qualcosa abbastanza come prima.
Quindi questo è l'indirizzo nel mio computer di ricordo di dove x si trova a vivere.
E 'Ox-qualcosa.
E questo è, francamente, perché Ho iniziato a disegnare frecce,
invece di numeri, perché a chi importa veramente
che il vostro int è in un particolare indirizzo che è così grande.
Ma bffff0c4, questi sono tutti anzi cifre esadecimali,
che sono da 0 a f.
>> Quindi non stiamo andando a soffermarsi troppo a lungo su ciò che quelle cose sono.
Ma se stampo fuori y, Naturalmente, vedo 2.
Ma ampersand y, vedo questo indirizzo.
E notate, per i curiosi, quanto distanti siano x e y?
È possibile ignorare la maggior parte dell'indirizzo.
Quattro byte.
E questo è coerente con la nostra precedenza affermare che quanto è grande un int?
Quattro byte.
Quindi sembra fodera del tutto up bene, come si potrebbe sperare, in memoria.
>> Così ora, diciamo solo avanti veloce alla fine di questa storia.
Andiamo avanti e tipo di passo, immergersi nella funzione Swap.
Ora notate, se si digita una, è identico all'indirizzo di x.
Se digito b, è identico all'indirizzo di y.
Quindi cosa devo vedere se ho dire, andare all'indirizzo un?
Quindi, stampare una stella.
Così stella significa andare lì, in questo contesto.
Ampersand indica qual è l'indirizzo.
Quindi protagonista un mezzo 1.
E stampa stella b mi dà 2.
>> E lasciatemi presumo, per il momento, che almeno il codice che
procede ad eseguire ora può essere motivata attraverso in quel modo.
Ma ci rivisitare questa idea in poco tempo.
Quindi questa versione di Swap ora è corretta e consente
ci scambiamo questo particolare tipo di dati.
>> Quindi, tutte le domande allora Swap?
Su stella?
Su indirizzo?
E vedrai, con problema set 4, sorta di,
ma problema set 5, sicuramente, come queste le cose sono utili e ottenere molto di più
bene con loro, come risultato.
Niente di niente?
Bene.
Quindi malloc è, ancora una volta, questa funzione che assegna solo la memoria, la memoria
allocazione.
E perché è utile?
Ebbene, tutto questo tempo, hai utilizzato malloc.
Se si considera ora come getString lavori, presumibilmente, è
stato chiedere a qualcuno per un pezzo di memoria, in qualsiasi momento l'utente digita una stringa
in, perché certamente non sapeva, come il personale CS50,
quanto grande quelle corde che gli esseri umani stanno per digitare potrebbe essere.
>> Quindi cerchiamo di, per la prima volta, iniziano a Staccare come funziona la biblioteca CS50,
mediante una coppia di esempi che ci porterà lì.
Quindi, se apro gedit e di aprire scanf 0,
stiamo andando a vedere il codice seguente.
Scanf 0, disponibile sul sito web di oggi, ha relativamente poche righe di codice
qui, da 14 a 20.
E vediamo che cosa sta facendo.
Si dichiara un int, chiamato x.
Si dice qualcosa del tipo, numero di favore.
E ora si dice, scanf% i, & x.
Quindi c'è un sacco di roba nuova c'è.
>> Ma scanf, è possibile tipo di pensare come l'opposto di printf.
printf, naturalmente, stampe alla schermata.
scanf sorta di scansioni da parte dell'utente del tastiera qualcosa che lui o lei ha digitato.
>> % I è proprio come printf.
Ciò significa che si aspettano l' all'utente di digitare un int.
E ora, perché pensi che io potrebbe essere passare scanf & x?
Se lo scopo della vita di scanf è quello di ottenere qualcosa da parte dell'utente,
qual è il significato di passarlo, & x, adesso?
Sì?
>> PUBBLICO: [incomprensibile].
DAVID J. MALAN: Esattamente.
Qualunque cosa io, l'umano, digitare, il mio ingresso sta per essere salvato in quella posizione.
Non è sufficiente ricordare, ad appena passare x, perché abbiamo visto già,
ogni volta che si passa solo una variabile grezza, come un int, a qualche altra funzione,
certo, si può cambiare la situazione variabile, ma non in modo permanente.
Non può avere un effetto sulla principale.
Si può cambiare solo la propria copia locale.
Ma se, invece, non lo fai dammi l'int reale,
ma tu mi dai le indicazioni per che int, ora, essendo scanf,
sicuramente, posso seguire che affrontare e mettere un numero non
in modo da avere accesso ad esso pure.
>> Così, quando ho eseguito questo programma, vediamo.
Fai scanf 0 dot barra, scanf 0.
E se io ora digito un numero come 50, grazie per la 50.
Se ora digito un numero come negativo 1, per il negativo 1.
Ora digitare un numero come 1,5, hm.
Perché il mio programma mi ignora?
Beh, semplicemente perché, ho detto ad aspettarsi solo un int.
Bene.
Ecco, questo è una versione di questo.
Prendiamo le cose su una tacca e propone che questo non è buono.
E qui si trova un esempio molto semplice di come possiamo iniziare la scrittura di codice
che altre persone possano sfruttare o compromettere facendo cose cattive.
Così la linea 16, così simili in spirito di prima,
ma io non sto dichiarando che int questa volta.
Sto dichiarandola stelle char, aka stringa.
>> Ma che cosa significa in realtà?
Quindi, se non si specifica un address-- e Sto chiamando arbitrariamente, tampone,
ma ho potuto chiamo s, per essere simple-- e poi faccio questo, spiegare a me,
se si potesse, sulla base della precedente logica, ciò che è scanf facendo in linea 18,
se il passaggio% s e tampone, che è un indirizzo?
Che cosa è scanf, se si applica il esatto stessa logica la versione 0,
intenzione di provare a fare qui, quando l'utente digita qualcosa?
Sì?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Esattamente.
Scanf, dalla logica precedente, sta andando a prendere la stringa
che la digitato umano dentro-- ora è una stringa,
non è un numero, presumibilmente, se lui o lei cooperates--
e sta andando a cercare di mettere che stringa in memoria a qualsiasi indirizzo
tampone specifica.
E questo è grande, perché tampone è infatti destinato ad essere un indirizzo.
>> Ma io sostengo questo programma è bacato in un modo molto serio, perché quello che è il valore
tampone di default?
Che cosa ho inizializzato in?
Che pezzo di memoria?
Io non ho, giusto?
>> Quindi, anche se ho assegnato una char stella che non si chiama s,
è invece chiamato, buffer-- così cerchiamo di disegnare il nome della variabile
ora come buffer-- se non ho chiamato getString o malloc qui,
che significa effettivamente che buffer è solo un valore spazzatura.
>> Ora, che cosa significa?
Significa che ho detto scanf aspettarsi una stringa dall'utente.
E sai una cosa?
Qualunque sia questa cosa sta indicando a-- e traggo punto interrogativo,
ma in realtà, sta andando ad essere qualcosa come OX1, 2, 3, giusto?
E 'un valore falso che appena capita di essere lì da prima.
Quindi, in altre parole, è come se buffer è solo
che punta a qualcosa in memoria.
Non ho idea di cosa.
>> Quindi, se digito Gabe ora, sta andando per cercare di mettere g-a-b-e / 0 lì.
Ma chi sa di cosa si tratta?
E in passato, qualsiasi tempo abbiamo cercato di toccare
memoria che non appartiene a noi, che cosa è successo?
O quasi ogni volta.
Segmentation fault, giusto?
>> Questa freccia, non ho idea di dove è puntamento. è solo un valore casuale.
E, naturalmente, se si interpreta un valore casuale come un indirizzo,
avete intenzione di andare a una certa destinazione casuale.
Così Gabe potrebbe infatti incidente il mio programma in questo caso qui.
>> Che cosa possiamo fare che è quasi peggio?
Considerate questo terzo e ultimo esempio di scanf.
Questa versione è meglio in che senso?
Se hai dimestichezza con la problema precedente, questo è meglio.
Perché?
>> PUBBLICO: [incomprensibile].
DAVID J. MALAN: Good.
Quindi questo caso della linea 16 è meglio, nel senso
che siamo esplicitamente allocazione della memoria.
Noi non stiamo usando malloc, stiamo usando la settimana 2
approccio di solo dichiarare un array.
E abbiamo detto prima che una stringa è solo un array di caratteri,
quindi questo è del tutto legittimo.
Ma è, naturalmente, come si nota, dimensione fissa, 16.
>> Quindi questo programma è totalmente sicuro, se digito
in stringhe di un carattere, due caratteri stringhe, 15 stringhe di caratteri.
Ma appena comincio a digitare 16, 17, 18, 1.000 stringhe di caratteri,
dove sta la stringa sta per finire?
Sta andando a finire in parte qui.
Ma poi chissà cos'altro è al di là dei confini
di questa particolare array?
>> E 'come se ho dichiarato 16 scatole qui.
Quindi, piuttosto che tirare fuori tutto 16, faremo solo finta che ho disegnato 16.
Ma se poi provo a leggere un stringa che è molto più lungo, come 50 caratteri,
Ho intenzione di iniziare a mettere a, b, c, d, x, y, z.
E questo è probabilmente qualche altro segmento di memoria
che, ancora una volta, potrebbe causare il mio programma di crash,
perché non ho chiesto qualcosa di più di soli 16 byte.
>> Quindi chi se ne frega?
Bene, ecco la biblioteca CS50.
E la maggior parte di questo è solo come le istruzioni sulla parte superiore.
La biblioteca CS50, tutto questo tempo, ha avuto questa linea in linea 52.
Abbiamo visto typedef, o si vedrà typedef
in pset 4, che crea solo un tradurre cui char stelle può essere più
semplicemente indicato come stringa.
Quindi questo è uno dei alcune ruote di formazione
abbiamo usato di nascosto sotto il cofano.
>> Nel frattempo, ecco la funzione getchar.
Ora a quanto pare, non c'è nessun corpo ad esso.
E infatti, se continuo scorrimento, io in realtà non
vedi tutte le implementazioni di queste funzioni.
Come un controllo di integrità, perché?
>> PUBBLICO: [incomprensibile].
DAVID J. MALAN: Già.
Quindi questo è il file di intestazione.
E file di intestazione contengono prototipi, più alcune altre cose, a quanto pare,
come typedef.
Ma in CS50.c, che abbiamo mai dato a titolo definitivo,
ma è stato nel apparecchio CS50 tutto questa volta, nel profondo delle sue cartelle,
notare che c'è un intero gruppo di funzioni in qui.
>> In realtà, cerchiamo di scorrere verso il basso.
Ignoriamo la maggior parte di loro, per ora.
Ma scorrere verso il basso per getInt e vedere come funziona getInt.
Così qui è getInt.
E se mai veramente curato come arrivare int funziona, ecco la sua documentazione.
E tra le cose che dice è che ti dice
quali gli intervalli di valori che possono tornare.
E 'essenzialmente negativo 2 miliardi al positivo 2 miliardi, prendere o lasciare.
>> E si scopre, tutto questo tempo, anche se non abbiamo mai
se aveste verificare la presenza di esso, se qualcosa va storto,
si scopre che tutti questa volta, ha getInt
state restituendo una speciale costante, non nullo,
ma piuttosto INT_MAX, che è convenzione solo un programmatore.
Significa: ecco un valore speciale.
Assicuratevi di controllare per questo, basta in caso qualcosa vada storto.
Ma non abbiamo mai disturbati con che fino ad oggi,
perché ancora una volta, questo si intende per semplificare.
>> Ma come fa getInt ottenere implementato?
Beh, si, ma non accetta argomenti.
Sappiamo che.
Esso restituisce un int.
Sappiamo che.
Così come funziona sotto il cofano?
>> Quindi c'è apparentemente un infinito ciclo, almeno l'apparenza di uno.
Notate che stiamo usando getString.
Ecco, questo è interessante. getInt chiama la nostra funzione, getString.
E ora perché potrebbe essere questo il caso?
Perché mi viene difensiva qui in linea 165?
Cosa potrebbe accadere in linea 164, tanto per essere chiari?
E 'la stessa risposta di prima.
Potrebbe essere solo la memoria.
Qualcosa va storto con getString, dobbiamo essere in grado di gestire questo.
E la ragione per cui non tornare nulla è che, tecnicamente, è un puntatore nullo.
getInt deve restituire un int.
Così ho arbitrariamente ha deciso, in sostanza,
che 2 miliardi, più o meno, sta ad essere un valore speciale che non potrò mai
effettivamente ottenere da parte dell'utente.
E 'solo un valore di Vado sprecare per rappresentare un codice di errore.
>> Così ora, le cose si fanno un po 'di fantasia.
E non è proprio la stessa funzione come prima, ma è molto simile.
Così Noto, dichiaro qui, in linea 172, sia un int n e un char c.
E poi io uso questa linea funky, sscanf, che si scopre
non eseguire la scansione di una stringa da tastiera.
Si trova una stringa esistente che l'utente ha già digitato.
Così ho già chiamato getString, che significa che ho una stringa in memoria.
sscanf è quello che ci si chiamare una funzione di parsing.
Esso esamina la stringa ho digitato, carattere per carattere,
e fa qualcosa di utile.
Tale stringa viene memorizzato in linea.
E so che solo andando eseguire il backup qui e dire, oh, OK,
Ho chiamato non s questa volta, ma la linea.
>> E ora questo è un po 'diverso.
Ma questo significa efficacemente, per motivi faremo un po 'sventoliamo le nostre mani a oggi,
che stiamo verificando a vedere se l'utente ha digitato in
e int e forse un altro personaggio.
Se l'utente ha digitato in un int, è andando a essere immagazzinate nella n, perché sono
passando da questo indirizzo, il nuovo trucco che abbiamo visto oggi.
Se l'utente anche digitato a come 123x, che x
sta per finire un lettera in carattere c.
>> Ora si scopre che sscanf mi dirà, in modo intelligente,
quante variabili è stato sscanf con successo in grado di riempire.
Così da questa logica, se la funzione Sto esecuzione è getInt,
ma io sto controllando, potenzialmente, per l'utente
di aver digitato in un int seguita da qualcosa d'altro,
cosa voglio di sscanf valore di ritorno veramente di essere?
Se lo scopo è quello di ottenere solo un int da parte dell'utente?
>> Quindi, se sscanf rendimenti 2, che cosa significa?
L'utente ha digitato in qualcosa di simile, letteralmente,
123x, che è solo una sciocchezza.
Si tratta di una condizione di errore, e Voglio controllare per questo.
>> Quindi, se l'utente digita questo, da questa logica, quello che fa sscanf ritorno,
diresti?
Così sta andando a tornare 2, perché la 123 sta per andare in qui,
e la x sta per finire qui.
Ma io non voglio la x per ottenere riempito.
Voglio sscanf per avere successo solo in riempiendo la prima delle sue variabili.
Ed ecco perché io Voglio sscanf per tornare 1.
>> E se questo è un po 'sopra la testa per il momento, che è totalmente soddisfacente.
Realizzare però, che uno dei valori di getInt e getString
è che noi stiamo facendo un diavolo di un sacco di controllo degli errori come questo così
che, ad oggi, si può tranquillamente digitare nulla a vostra tastiera,
e noi prenderlo.
E certamente, il personale, non sarà sicuramente
essere la fonte di un bug nel programma, perché siamo sulla difensiva
controllando tutti i stupido cose che un utente potrebbe fare,
come digitando una stringa, quando si voleva davvero int.
Quindi per now-- verremo Torna alla prima long--
ma tutto questo tempo, getString e getInt hanno
stato sotto la cappa di utilizzare questo idea di base di indirizzi di memoria.
>> Così ora, facciamo le cose un poco user-friendly più.
Come ricorderete, da Binky ultimo tempo-- se il mio mouse si cooperate-- così
abbiamo avuto questo codice, che francamente, è abbastanza assurdo.
Questo codice ottiene nulla utile, ma è stato l'esempio
quel professore Parlante utilizzato per rappresentare
quello che stava succedendo in un programma che coinvolge la memoria.
>> Quindi cerchiamo di raccontare questa storia eccellente brevemente.
Queste prime due righe, in Inglese, fai quello, diresti?
Proprio in ragionevolmente umano, ma leggermente termini tecnici, prendere una pugnalata.
PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: OK, siete stabilire indirizzi per la vostra variabili x e y.
Non proprio, perché x e y non sono variabili in senso tradizionale.
x e y sono indirizzi o memorizza l'indirizzo.
Quindi proviamo una volta di più.
Non male come inizio, però.
Sì?
>> PUBBLICO: [incomprensibile].
DAVID J. MALAN: Good.
Penso che sia un po 'più pulito.
Dichiarare due puntatori, due interi.
E stiamo chiamandoli x e y.
Oppure, se dovessimo disegnare questo come un quadro, di nuovo,
ricordare semplicemente che tutti stiamo facendo con quella prima linea
sta disegnando una scatola come questa, con un certo valore spazzatura in esso,
e chiamandolo X, e poi un'altra scatola come questo,
con un certo valore di immondizia in essa, chiamandolo a.
Abbiamo dichiarato due puntatori che in ultima analisi
memorizza l'indirizzo di un int.
Ecco, questo è tutto lì.
>> Così quando Binky ha fatto questo, il argilla appena guardato come questo.
E Nick solo tipo di avvolto le frecce,
come se non stanno puntando ovunque in particolare, perché sono solo
valori di immondizia.
Non sono esplicitamente inizializzate ovunque in particolare.
>> Ora la prossima linea di codice, richiamo, era questo.
Quindi, in ragionevolmente user-friendly, ma l'inglese un po 'tecnico,
che cosa è questa riga di codice facendo?
Sì?
>> PUBBLICO: [incomprensibile].
>> DAVID J. MALAN: Perfetto.
E 'assegnazione della fetta del memoria che è la dimensione di un int.
E questo è la metà della risposta.
Hai risposto il diritto metà dell'espressione.
Che cosa sta accadendo sul lato sinistro del segno di uguale?
Sì?
PUBBLICO: e assegna alla variabile x?
>> DAVID J. MALAN: e assegna alla variabile x.
Quindi, per ricapitolare, destra assegna laterali memoria sufficiente per memorizzare un int.
Ma malloc specificamente restituisce l'indirizzo
di quel pezzo di memoria, che hai appena proposto viene memorizzato in x.
>> Così che cosa ha fatto Nick ultima volta con Binky è che ha trascinato il puntatore fuori, l'argilla,
per puntare ora ad un pezzo bianco di memoria che è uguale alla dimensione di un int.
E in effetti, che è destinata per rappresentare quattro byte.
>> Ora, la prossima riga di codice fatto questo, stella x ottiene 42.
Quindi 42 è diretto sul destra, senso della vita.
Lato sinistro, stella x significa ciò?
Anche questo potrebbe avere gone-- che è OK.
Ok.
>> PUBBLICO: Fondamentalmente, andare al [incomprensibile]
DAVID J. MALAN: Good.
PUBBLICO: [incomprensibile].
DAVID J. MALAN: Esattamente.
Sinistra significa andare a x.
x è l'indirizzo.
E 'come 33 Oxford Street, o OX1.
E stelle x significa andare a quel affrontare e mettere quello che c'è?
42.
>> Così in effetti, questo è esattamente quello che ha fatto Nick.
Ha iniziato con da, in sostanza, mentalmente
puntando il dito contro x, seguendo la freccia
per la scatola bianca sulla destra lato, e mettendo il numero 42 lì.
Ma poi le cose sono un po 'pericoloso, giusto?
Binky sta per perdere la testa.
>> Stella y è uguale a 13, la sfortuna, che cosa significa?
Così stella mezzi y vanno all'indirizzo di y.
Ma qual è l'indirizzo in y?
Va bene, il suo valore spazzatura, giusto?
Ho disegnato come un punto interrogativo.
Nick ha attirato come una freccia rannicchiata.
E non appena si tenta di fare stella y, dicendo andare lì,
ma non c'è un legittimo indirizzo, è certa posizione falsa,
il programma sta andando in crash.
E la testa di Binky sta a volare fuori qui, come ha fatto.
>> Così, alla fine, questo programma era appena flat out difetto.
E 'stato un programma buggy.
E aveva bisogno di essere fissato.
E l'unico modo, davvero, per risolvere il problema sarebbe, per esempio, questa linea,
che non abbiamo neanche raggiungere, perché il programma si è schiantato troppo presto.
Ma se dovessimo risolvere questo problema, cosa effetto fa fare y pari x hanno?
Beh, che punti essenzialmente aa qualsiasi valore x punta verso.
>> Così nella storia di Nick, o la storia di Binky, sia
x e y sono state rivolte l'una verso il pezzo bianco della memoria,
in modo che, alla fine, quando si non a stella Y è uguale a 13 di nuovo,
si finisce per mettere 13 in nella posizione appropriata.
Quindi tutte queste linee sono perfettamente legittima, tranne per questo,
quando è successo prima di effettivamente assegnato un certo valore y.
>> Ora per fortuna, non è necessario avere a ragionare attraverso tutti
di questi tipi di problemi da soli.
Lasciami andare avanti e aprire una finestra di terminale qui
e di aprire, solo per un attimo, un super breve programma che
è anche una sorta di inutile.
E 'brutto.
Essa non ottiene nulla di utile.
Ma questo dimostra questioni della memoria, così diamo un'occhiata.
>> Principale, super semplice.
E a quanto pare chiama una funzione, F, e quindi restituisce 0.
È un po 'difficile da rovinare questo.
Quindi principale è abbastanza buono, finora.
>> Quindi f è problematico.
E proprio non ha messo molto sforzo in nominarlo
qui, per mantenere l'attenzione sul codice.
f ha due linee.
E vediamo quello che sta ora accadendo.
Così, da un lato qui-- e fammi fare
questa linea con il precedente example-- da un lato,
il lato sinistro è facendo ciò, in inglese?
Si è--
PUBBLICO: Creazione di un puntatore.
DAVID J. MALAN: Creazione di un puntatore ad un int e chiamandolo x.
Così è la creazione di una di quelle scatole Continuo a disegnare sul touch screen.
E ora, sulla destra lato, malloc, naturalmente,
è l'assegnazione di un pezzo di memoria.
E tanto per essere chiari, come quantità di memoria è apparentemente
assegnazione, se solo tipo di fare la matematica qui?
>> Quindi è 40 byte.
E so che solo perché so un int, sull'apparecchio CS50, almeno,
è quattro byte.
Quindi 10 volte 4 è 40.
Quindi questa è la memorizzazione di un x, l'indirizzo del primo dei 40 int che
sono stati stanziati spazio posteriore, to back, to back, to back.
>> E questo è ciò che è chiave su malloc.
Non ci vuole un po 'di memoria qui, un po 'qui, un po' qui.
Ti dà un pezzo di memoria, contiguo, dal funzionamento
sistema.
>> Ora, che dire di questa, x staffa 10 è uguale a 0?
Linea arbitraria di codice.
Essa non ottiene nulla di utile.
Ma è interessante, perché x staffa 10--?
Sì?
>> PUBBLICO: [incomprensibile]?
>> DAVID J. MALAN: x staffa 10 non deve essere nullo.
Il dettaglio nulla entra in gioco solo con corde, alla fine di una stringa.
Ma un buon pensiero.
>> Quanto è grande questo array, anche se ho assegnata 40 byte?
E 'da 0 a nove, giusto?
E '10 int, totale.
40 byte, ma 10 int, indicizzate da 0 a 0.
>> Così che cosa è che la staffa x 10?
In realtà è un po ' sconosciuta valore spazzatura.
E 'la memoria che non appartiene a me.
Non dovrei toccando che byte numero 41, 42, 43, 44.
Sto andando un po 'troppo lontano.
>> E in effetti, se corro questo programma, potrebbe benissimo bloccarsi.
Ma a volte, ci arriveremo fortunati.
E così, proprio per dimostrare Questa poi e, francamente,
non si sa mai prima di do it-- corriamo questo.
Essa in realtà non crash.
>> Ma se cambio questo, per esempio, di essere come 1000,
per rendere questo veramente deliberata, vediamo
se possiamo ottenere il crash questa volta.
OK, non è precipitato.
Come circa 100.000?
Cerchiamo di rifarlo, e ora eseguirlo nuovamente.
Ok.
Uff.
Bene.
Quindi, apparentemente, ancora una volta, questi segmenti di memoria, per così dire,
sono abbastanza grande, in modo che possiamo ottenere ancora e ancora fortunati.
Ma alla fine, una volta arrivati ​​ridicolo e davvero andare lontano sullo schermo,
si tocca la memoria che in realtà, in realtà non appartiene a voi.
>> Ma francamente, questi tipi di insetti stanno andando
per essere sempre più difficile di capire da soli.
Ma per fortuna, come i programmatori, abbiamo strumenti che ci permettono di fare questo per noi.
Quindi questo è, forse, uno dei programmi più brutti,
anche più brutto di uscita di gdb.
Ma ha sempre una linea o due che sono super utile.
>> Valgrind è un programma che aiuta non si esegue il debug di un programma, di per sé,
ma trovare relative alla memoria problemi, in particolare.
Verrà eseguito automaticamente il codice per voi e cercate almeno due cose.
Uno, hai fatto qualcosa accidentale come la memoria di tocco
che non apparteneva a voi?
Essa vi aiuterà a trovare quei casi.
>> E due, che vi aiuterà si trova qualcosa chiamato
perdite di memoria, che abbiamo completamente ignorato, ingenuamente,
per qualche tempo e beatamente.
Ma si scopre, tutto questa volta, ogniqualvolta
che hai chiamato in getString così molti dei nostri programmi,
si sta chiedendo il funzionamento sistema per la memoria,
ma avete alcun ricordo di sempre dando
indietro, facendo unalloc, o libero, come si chiama.
No, perché non abbiamo mai ti ha chiesto di farlo.
>> Ma tutto questo tempo, i programmi hai scritto in C
sono state perdite di memoria, chiedendo il funzionamento
Sistema per più memoria per archi e quant'altro,
ma mai restituirlo.
E ora questo è un po ' di una semplificazione,
ma se hai mai eseguito il vostro Mac o il PC per un bel po 'di tempo, l'apertura
un sacco di programmi, forse chiudere i programmi,
e anche se la vostra computer non è andato in crash,
sta diventando così molto più lento, come se fosse davvero
utilizzando un sacco di memoria o risorse, anche se,
se non sei nemmeno toccare la tastiera,
che potrebbe essere-- ma non ci riuscivo always-- essere che i programmi si sta eseguendo
hanno essi stessi perdite di memoria.
E loro continuano a chiedere il sistema operativo per sempre più memoria, ma dimenticando che,
in realtà non usarlo, ma quindi prendendo la memoria di distanza
da altri programmi che potrebbero desiderare di esso.
Ecco, questo è una spiegazione comune.
Ora qui è dove Valgrind di uscita è completamente
atroce a quelli meno e più confortevole simili.
Ma l'interessante roba è proprio qui.
Mi sta dicendo una scrittura non valido dimensione quattro succede in questo programma,
in particolare, alla riga 21 di memory.c.
>> Se vado alla riga 21, hm, c'è davvero è una scrittura valida di dimensione quattro.
Perché quattro dimensioni?
Beh, questo number-- e potrebbe essere anything-- è un int.
Quindi è quattro byte.
Così sto mettendo quattro byte cui non appartengono.
Questo è ciò che Valgrind è in realtà mi dice.
Inoltre, sarà anche dimmi, come vedremo,
come si esegue questo in un futuro pset, se e quando hai trapelare la memoria, che anzi
Ho, perché ho chiamato malloc, ma io non ho fatto
chiamato, in questo caso, libero, che vedremo poi vediamo
è l'opposto di malloc.
>> Così ora, penso, un ultimo esempio.
Quindi questo è un po 'più arcano, ma è forse
il più grande motivo di stare attenti con la memoria,
e la ragione per cui molti programmi e / o server web, anche a questo giorno,
sono preso da cattivi da qualche parte su Internet che sono in qualche modo
l'invio di pacchetti falsi al vostro server cercando di compromettere i vostri conti,
o prendere i vostri dati, o semplicemente generalmente assumere una macchina.
Buffer overflow, come l' nome suggerisce, mezzi
traboccante non un int, ma un buffer.
E un buffer è solo un modo elegante di dire che è un po 'di memoria.
>> E in effetti, ho chiamato una stringa prima tampone, invece di s.
Perché se si tratta di un buffer, come nel senso di YouTube,
o in qualsiasi momento si sta guardando un video, potreste aver visto la parola buffering,
dot, dot, dot.
E 'incredibilmente fastidioso.
E questo significa solo che il vostro lettore video
sta cercando di scaricare un sacco di byte, un sacco di byte
da un video da internet.
Ma è lento, quindi si sta cercando per scaricare un gruppo di loro
per riempire un buffer, un contenitore, in modo che si dispone di un numero sufficiente di byte che si può poi
mostrare il video, senza pause costantemente.
Ma si scopre, è possibile hanno un buffer per questo grande.
Ma provate a mettere questa quantità di dati in esso, e molto cose brutte possono accadere.
Così, per esempio, diamo un'occhiata a questo teaser finale di un esempio.
Questo è un altro programma che, a prima vista,
non fa nulla super utile.
Ha una funzione principale che chiama tale funzione, f.
E che funzione, f, qui, ha un array di char, chiamato C, di dimensione 12.
E poi si sta usando questo nuova funzione chiamata strncpy.
>> Risulta che, con questa semplice, semplice riga di codice, solo due righe,
abbiamo fatto tutto il mio programma, e, quindi, tutto il mio computer,
e il mio account, e il mio duro guidare potenzialmente vulnerabili a chiunque
che conosce ed è abbastanza buono per correre questo programma con una certa linea di comando
argomentazione.
In altre parole, se questo cattivo ragazzo mette dentro di argvargv [1] digitando
alla tastiera molto appositamente predisposto stringa, non abc, 123, ma essenzialmente,
simboli binari che rappresentano eseguibile codice, un programma che lui o lei ha scritto,
con questo semplice programma, che è rappresentativo di migliaia di programmi
che sono vulnerabili allo stesso modo, oserei dire, lui o lei può in ultima analisi, eliminare tutti
i file sul mio hard disk, ottengono un lampeggiante rapida in modo che lui o lei può
digitare i comandi per conto proprio, e-mail tutti i file a me.
Tutto ciò che posso fare, ha o lei può fare con questo codice.
>> Non abbastanza risolverà questo ancora.
E in effetti, sta andando a coinvolgere un po 'di foto
come questo, di cui parleremo presto per capire tutto il meglio.
Ma per oggi, finiamo su ciò che è, si spera, un po 'più
comprensibile scherzo XKCD, fino a quando riprendiamo la prossima volta.
Bene.
Ci vediamo il Mercoledì.
>> [GIOCO MUSICA]
>> SPEAKER: E ora, profondo pensieri, da Daven Farnham.
La memoria è come saltare in un mucchio di foglie d'oro in un pomeriggio di Domenica.
Vento che soffia, lanciando la vostra hair-- oh, mi mancano i giorni when--
>> [Risate]