>> [MUSIC PLAYING]
>> DAVID J. MALAN: Va bene questo è CS50 e questo è l'inizio di settimana cinque.
Così oggi, sotto i cuscini di seduta, non troverete nulla.
Ma, soprattutto, si dovrebbe trovare questi, un piccolo segno del nostro apprezzamento per il
tutto il lavoro che hai messo nel Gioco dei Quindici.
Basta rimuovere il piccolo cerchio sul fondo per iniziare a giocare per la
resto della classe.
>> Così ricordare che, o sapere che problema posto quattro, che è uscito questo fine settimana,
comporta la scrittura di un altro gioco.
Ma questa volta comporta l'uso di un interfaccia utente grafica effettiva, non una
interfaccia testuale come Gioco del Quindici è stato.
E il gioco che si trova davanti a voi, se non avete ancora visto questo prossimo,
sembra un po 'qualcosa di simile a questo.
Ho intenzione di andare nel mio terminale finestra qui a GDB.
E ho intenzione di andare avanti ed eseguire il soluzione personale, cui è possibile accedere
dopo l'esecuzione di update 50 come al solito.
>> Ma ho intenzione di metterla in un po 'di modo segreto, un piccolo uovo di Pasqua,
cosiddetta modalità di Dio, da mettere Dio in argv1.
E devo seguire le mie indicazioni, eseguirlo nel mio
problema impostare la directory.
Così ora si vede una versione completa del gioco di Breakout.
In realtà, questo è modalità nessuna mani.
Quindi, in realtà -
entusiasmato anche se si potrebbe essere -
abbastanza banale da implementare la modalità Dio in Breakout, a differenza del gioco di quindici anni,
che alcuni di voi hanno affrontato per l'edizione di hacker.
>> In Breakout è sufficiente in Dio Modalità di semplicemente fare ciò,
intuitivamente con la pagaia?
Basta fare uguale qualunque sia il posizione orizzontale è della palla.
E fino a quando si esegue questa operazione in sincronia con la palla in movimento questo gioco sarà
mai, mai, mai perdere la palla e potrai vincere ogni volta.
>> Ma in questa settimana edizione di hacker c'è più di un semplice modo di Dio.
C'è una serie di altre funzioni.
Tra questi, i laser.
In modo che se hai davvero impaziente di può iniziare abbattere i mattoni
e pochi altri.
E per quelli di voi che vorrebbe calibrare Standard piuttosto che degli hacker
edizione, vedo che di questa settimana edizione degli hacker volutamente è un
poco più fattibile, per dire, che Dio Modalità era con Gioco del Quindici.
>> Quindi, se siete alla ricerca di un tratto e di siete alla ricerca di un po 'di divertimento aggiuntivo
caratteristiche fanno immersione in caso di interesse.
Ora più praticamente, vorrei sottolineare fuori una cosa così.
GDB, che alcuni di voi potrebbero non avere ancora toccato personalmente, che va bene.
Ma ora è davvero il tempo di abituarsi per questo e confortevole con questo strumento
perché renderà la vostra vita molto più semplice, veramente.
>> A lezione di Rob su GDB una coppia di settimane fa, ricordare
che GDB è un debugger.
E 'uno strumento che consente di eseguire il vostro programma, ma eseguito passo passo, linea
per riga, in modo che sia possibile esplorare, in modo che si vedono le cose accadere, così
che è possibile stampare valori delle variabili.
In breve, ti dà molto di più potere che printDef fa.
>> Ora è vero, l'interfaccia è piuttosto arcano.
Interfaccia testuale in bianco e nero per la maggior parte.
I comandi sono un po 'duri ricordare a prima.
Ma anche se si potrebbe prendere la metà un'ora, un'ora, per mettere che in anticipo
investimento di tempo in esso, fidati di me.
Certamente entro la fine del semestre, la salverà voi un ordine di grandezza più
tempo di quello.
>> Così all'inizio della settimana tuffarsi dentro
E in termini di Breakout, sapere che si può fare questo in modo finché si dispone di
il codice di distribuzione o il proprio codice in corso nella vostra directory Pst4.
Sappiate che è possibile eseguire gdb. / Breakout.
>> Questo sta per aprirsi una finestra come questa.
Lasciate che mi do più di una finestra di terminale.
E allora che cosa ho intenzione di andare avanti e fare, non è solo eseguirlo.
Ho intenzione di impostare prima un punto di rottura richiamo, che consente di mettere in pausa
esecuzione in un luogo particolare.
>> Giusto per mantenere le cose semplici Vado a rompere in linea uno semplicemente digitando
il numero uno.
Lasciatemi in realtà riaprire questa finestra perché si sta facendo un
piccolo piccolo lì.
Quindi quello che sto ora intenzione di fare qui è se apro la mia finestra di terminale.
Dai, ci siamo.
>> Così ora se torno al set, Pst4 ed eseguire gdb. / breakout entrare, si noti
Io vado a rompere uno per impostare un punto di interruzione alla riga uno.
E ora ho intenzione di andare avanti e di tipo gestito.
E quando lo faccio, non accorgersi di nulla sembra accadere.
>> Non c'è nessun pop-up.
Non c'è alcun grafico interfaccia utente ancora.
Ma questo è comprensibile perché sono letteralmente in linea uno nel mio programma.
E notare che non ho fretta trasmesso, specificamente ora a 62, perché tutti
la roba nella parte superiore di questo file è cose come i commenti e le costanti e
poco interessante roba per ora.
>> Così ora sono all'interno del principale, a quanto pare, alla riga 62.
E questo è solo la distribuzione codice, richiamo.
Se apro questo up andando, allo stesso modo, nella mia cartella drop box in Pst4,
in breakout.c.
E se ho scorrere verso il basso e verso il basso e verso il basso, e mi permetta di andare avanti e accendo
i miei numeri di riga.
>> Che cosa vedrò, se ho scorrere verso il basso per linea 62, è esattamente la linea che
ci siamo soffermati su.
Così questa linea qui, 62 anni, è dove stiamo per essere.
Così ora in GDB, se vado avanti e digito ora successiva, immettere sta andando a
eseguire quella linea.
E voilà, abbiamo il cosiddetta finestra g.
Se non hanno familiarità con ciò che un GWindow è, di non preoccuparsi.
La spec vi introdurrà ad esso, come così come una serie di video walkthrough
incorporato nella spec.
>> Ma ora facciamo questo un po 'più interessante.
Permettetemi di spostare questa finestra sopra per il lato un po '.
Permettetemi di fare un po 'la finestra più grande in modo da poter vedere di più.
>> E ora lasciami andare avanti e fare dopo di nuovo.
E ci sono i miei mattoni.
Se digito prossima volta ora vedo la palla.
E se scrivo di nuovo Avanti ora vedo la pagaia.
>> E per fortuna questo non è gedit davvero cooperare mostrando me
tutto quello che voglio.
Ma ora, se devo fare di nuovo, prossima volta, sono solo
che dichiara alcune variabili.
E posso stampare una qualsiasi di questi ragazzi fuori.
Mattoni di stampa, stampe vite.
>> E ora se continuo a fare prossimo, noto che sarò
all'interno di quel ciclo.
Ma il codice sta per eseguire esattamente come mi aspetto.
Così, quando mi ha colpito di questa funzione, attendere per Click, è andare a fare
letteralmente questo.
Così mi sembrava di aver perso il controllo sul programma.
>> GDB non mi sta dando un nuovo prompt.
Ma non preoccupatevi.
Vai al mio gioco, cliccare da qualche parte.
>> E voilà, adesso si procede alla linea 86.
Quindi, di nuovo, è un valore inestimabile, in ultima analisi, per problemi di debug.
Perché si può letteralmente scorrere il codice, le cose stampare e molto,
molto, di più.
Ma per ora, questi soli strumenti dovrebbe arrivare abbastanza lontano.
>> Quindi siamo, ovviamente, dare un'occhiata in grafica ora, tutto d'un tratto.
E ora il nostro mondo diventa un po ' più interessante.
E si sa, forse, da alcune delle video online che abbiamo questi
pantaloncini che siete stati a guardare come parte del set problema.
>> E sono stati fucilati, deliberatamente, contro uno sfondo bianco.
E alcuni di loro hanno l'insegnamento Fellows disegno del testo sul
schermo che è sovrapposta sul lato di loro.
Ma, naturalmente, questo non è tutto ciò che interessante nel mondo reale.
Questa è solo una sala conferenze con una grande schermo bianco e sfondo.
E il nostro incredibile team di produzione di specie di fa sembrare tutto bello
dopo il fatto da ritaglio fuori o sovrapponendo nulla
che facciamo o non vogliamo.
>> Ora basta per motivare questa settimana e davvero, dove si può andare, in ultima analisi,
con l'informatica.
Non solo dopo problema impostare quattro.
Ma dopo un altro corso o di un intero curriculum è incredibile quello che si può
fare in questi giorni, in termini di grafica in particolare.
>> Alcuni di voi avranno visto questo scorre intorno online.
Ma ho pensato di mostrarvi, solo per un paio di minuti, un assaggio di quello
tecnologie informatiche e quali CGI, computer grafica può fare in questi giorni
con una canzone familiare e forse film.
>> [MUSICA - Lana Del Ray, "Giovane e bella]
>> SPEAKER 1: E 'solo un po' sorprendente, forse, proprio come
onnipresente -
>> [Applausi]
>> SPEAKER 1: Ho appena scaricato.
Ma è davvero incredibile, credo, solo come il software onnipresente e codice e
strumenti come questo sono davvero.
Ecco, questo è un assaggio della direzione in cui si può andare.
Oh, non più Appliance oggi.
Beh, questo è tempismo davvero tragica dato il punto ho solo cercato di fare.
>> Va bene, quindi cerchiamo di lanciare Fusion nuovo.
Ricorda in seguito.
Va bene, e si dovrebbe aver ricevuto un e-mail come un a parte se hai fatto prendere un
notare come tale.
Va bene, quindi ricordare che la scorsa settimana abbiamo iniziato a staccare questo
più tardi conosciuta come stringa.
>> stringa richiama un tipo di dati che è dichiarata nella libreria CS50.
Ed è parte delle ruote di formazione che inizierà a decollare.
E 'stato un concetto utile nella fase iniziale.
Ma ora sta andando per ottenere più interessante e più potente per
effettivamente vedere che sotto il cofano, una stringa è proprio quello che, abbiamo detto?
>> Sì, quindi è un cosiddetto char *.
E il * ci indica che non c'è qualche tipo di indirizzo coinvolti.
E così quando si dice char * basta dire una variabile il cui tipo di dati è un
puntatore ora.
Il fatto che ci sia la star lì significa solo che si dichiara un
cosiddetti puntatore.
E questo puntatore è andare a quanto pare memorizzare l'indirizzo, di
Naturalmente, un char.
>> Ora, perché questo ha senso?
Ebbene, che cosa è una stringa sotto il cofano?
Beh, da qualche tempo che abbiamo detto che una stringa sotto la cappa è
appena h-e-l-l-o, per esempio.
>> Ma abbiamo parlato di questo come essendo, in sostanza, un array.
E una serie sarebbe poi guardare un po ' Prodotto, con ciascuno di questi
prendendo un morso.
E poi abbiamo detto che non c'è qualcosa di speciale qui dietro, il
backslash 0 o null terminator.
>> Quindi tutto questo tempo, questo qui è stata una stringa.
Ma in realtà, una stringa è in realtà un indirizzo.
E indirizzi, come vedremo, sono spesso con il prefisso 0x per convenzione.
Che cosa significa 0x denotano?
Qualcuno lo sa?
>> Quindi significa solo esadecimale.
Così si potrebbe ricordare, in realtà, da Pst 1, credo, uno dei warm-up
domande effettivamente chiesto notazione esadecimale in aggiunta a
binaria e decimale.
E la motivazione qui è che con esadecimale hai 16
cifre a vostra disposizione.
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, seguita da a, b, c, d, e, f.
>> E se si contano tutti coloro up, si ottiene un totale di 16.
Quindi questo è in contrasto con decimale, dove abbiamo 10
cifre, da 0 a nove.
E 'in contrasto con binario dove dobbiamo solo 0 e 1.
>> Ma alla fine della giornata, si può solo rappresentare gli stessi numeri, ma
un po 'diverso.
E esadecimale è comune, perché come si scopre - e vedremo questa
successivamente nel corso - anche quando otteniamo alla programmazione web in un contesto di
HTML e codici di colore, esadecimale è bello.
Perché ogni cifra, risulta, rappresenta perfettamente quattro bit.
Quindi è solo tipo di linee su piacevolmente come vedremo alla fine vediamo.
Quindi questo potrebbe essere Ox123 o qualcosa come quello, che denota l'indirizzo 123
da qualche parte dentro di mia memoria del computer.
>> Ma, naturalmente, alcuni problemi sorgono a causa di questo sottostante
attuazione.
E ricordo che ho preso una pugnalata a implementazione di una funzione come questa -
confrontare dash 0 dot c scorsa settimana, che anche se sembrava che fosse
giusto, semplicemente non paragonabile due stringhe correttamente.
>> Ho buttato via principale, e ho buttato via i commenti solo a concentrarsi su
il codice che è di interesse qui.
Ed è in rosso perché è bacato.
Per quale motivo?
>> Beh, in cima lì quando ho dichiarato una stringa, che cosa stava realmente accadendo
sotto il cofano?
Beh, mi permetta di andare oltre la schermare qui e disegnare quello.
Così ho dichiarato, ancora una volta, GetString stringa s.
>> Quindi ho intenzione di andare avanti ora e disegnare s per quello che è veramente.
Sta andando essere un quadrato qui.
E ho intenzione di rivendicare che questo è 32 bit.
Almeno di solito è, almeno sul CS50
apparecchio in un sacco di computer.
Io vado a chiamare s.
>> Ma ora ricordare che noi chiamato GetString.
Ritorna così GetString, naturalmente, una stringa.
Se l'utente digita in h-e-l-l-o entrano la stringa ciao viene restituito.
E quella stringa, come abbiamo appena detto, si conclude da qualche parte nella memoria del computer
con un backslash 0 alla fine.
Io traggo questa come la matrice - o blocco contiguo di caratteri -
che in realtà è.
>> E ora, che cosa è GetString in realtà il ritorno?
Che cosa è stato GetString tornando tutto questo tempo?
Beh, diciamo, in settimane prima, restituisce una stringa.
Ma, più tecnicamente, cosa fa GetString ritorno apparentemente?
>> PUBBLICO: Un indirizzo.
>> SPEAKER 1: Un indirizzo.
Specificamente restituisce l'indirizzo del il primo boccone, qualunque essa sia.
Continuo a usare una, due, tre perché è conveniente.
>> Esso restituisce l'indirizzo del primo carattere della stringa.
E abbiamo detto la scorsa settimana che ciò è sufficiente.
Perché possiamo sempre capire dove la fine della stringa semplicemente
iterando su di esso, forse, con una per loop o di un ciclo while o qualcosa di simile
che, solo in cerca di "backslash 0", il carattere speciale sentinella.
>> E poi sappiamo che la stringa sembra essere di lunghezza -
in questo caso -
cinque.
Quindi tecnicamente cosa GetString fa è restituisce Ox123 in questo caso.
E tecnicamente quello che poi accade è che noi conserviamo, dentro di s, Ox123.
Alla fine della giornata, anche se questo è di nuova concezione, puntatori, sono
solo le variabili.
Ma capita di memorizzare i bit che rappresentare collettivamente un indirizzo.
Quindi tecnicamente tutto ciò che ottiene memorizzato in s è Ox123.
>> Ma noi, come esseri umani -
compreso oggi in poi -
sono davvero non andare a prendersi cura, in genere, quello che l'indirizzo sia
di qualche pezzo di memoria.
E 'solo a basso livello di dettaglio per essere intellettualmente interessante.
Quindi ho intenzione di annullare questo.
E invece, di più alto livello, basta dire che quando si parla di puntatori
Io vado a disegnare solo più freccia di facile uso che trasmette il
stessa idea e astrae le particolari di ciò che l'attuale
indirizzo di fondo è.
>> Ora, se torniamo al codice, cosa è successo la scorsa settimana se abbiamo stringa t
uguale GetString?
Beh, se ho di nuovo, digitare ciao questa volta ho intenzione di ottenere
un altro pezzo di memoria.
h-e-l-l-o backslash 0.
>> Ma perché ho chiamato GetString una seconda volta -
e so che questo da guardare il codice sorgente per GetString - anche
anche se è una coincidenza che il ciao era digitato due volte, GetString non è
andando a cercare di ottimizzare e di essere intelligente.
E 'solo andando a prendere un altro pezzo di memoria dal computer, che è
sta per essere a un altro indirizzo.
Diciamo arbitrariamente solo dire 456.
>> E allora che cosa sta andando per tornare?
E 'intenzione di tornare 456 e conservarla in t.
Così che cosa sta realmente accadendo, sul sinistra è che ho un altro pezzo
di memoria, tipicamente 32 bit.
E lì sta per andare Ox456.
Ma ancora una volta, io non sono interessato a questi particolari numeri più.
Sto solo andando a astrattamente disegnare come una freccia.
>> Quindi questa è ora una nuova spiegazione.
Ma è la stessa idea esatta che è sta accadendo tutto questo tempo.
E così la ragione allora, che questo primo versione del confronto era buggy
la scorsa settimana è il motivo?
Quando si esegue, se s è uguale uguale t Che cosa siete veramente
sotto la cappa confrontando?
>> Di confrontare gli indirizzi.
E proprio intuitivo, chiaramente, Ox123 non è andare a pari Ox456.
Quei numeri, questi bit sono solo diversi.
>> E così sempre, la settimana scorsa ha detto si digita cose diverse, anche se il
parole erano pari pari la stessa.
Così possiamo risolvere questo problema.
In parole povere, ciò che è stata la correzione?
>> AUDIENCE: Utilizzare una funzione.
>> SPEAKER 1: Utilizzare una funzione.
O stelle sono sicuramente coinvolti, ma utilizzare una funzione per fare cosa?
>> PUBBLICO: Per confrontare le stringhe.
>> SPEAKER 1: Per confrontare le stringhe.
Quindi, il problema fondamentale qui è stato che stavo solo prendendo in considerazione il
qualità di stringhe da essere definito da confronto dei loro indirizzi.
E, ovviamente, questo è solo stupido ora una volta si capisce che cosa sta succedendo
sotto la cappa.
Per confrontare veramente stringhe per vedere se sono uguali nel senso che un umano
vorrei considerare due stringhe siano uguali abbiamo bisogno di confrontarli carattere per
carattere per carattere.
>> Ora avrei potuto fare questo molto noioso.
Ma familiarmente, siamo utilizzando un ciclo for.
E basta confrontare staffa s I contro t staffa i.
s Staffa i più 1 contro t staffa I più 1, e così via, all'interno
qualche tipo di ciclo.
E se ho posto le due personaggi che differiscono, o se mi rendo conto che ooh, s è
più breve o più lungo t t Posso subito dire falso,
non sono la stessa cosa.
>> Ma se ottengo attraverso s e t e dico stesso, stessa, stesso, medesimo, stesso, fine
entrambe le stringhe, posso dire vero, sono uguale.
Beh, per fortuna, anni fa qualcuno ha scritto che il codice per noi.
>> E lo chiamavano StrComp per la stringa di confronto.
E anche se è un po 'contatore intuitivo, StrComp restituisce 0 se quelli
due stringhe, s e t sono uguali.
Ma restituisce valore negativo se s dovrebbe venire prima di t in ordine alfabetico o
valore positivo se deve venire dopo t in ordine alfabetico.
>> Quindi, se mai desidera ordinare qualcosa, si scopre che StrComp è utile.
Perché non si limita a dire sì o no, uguale o meno.
Ti dà un senso di ordine come una forza dizionario.
Così StrComp, s virgola t è uguale a vale 0 significa che il
stringhe sono davvero uguali.
Perché chi ha scritto questa funzione anni fa, presumibilmente utilizzato un ciclo for
o un ciclo while o qualcosa di simile integrare sui caratteri nuovamente
e ancora e ancora.
>> Ma due problemi sorsero qui.
Questo era copy0.c.
Ed i due in rosso è perché è viziata.
E cosa abbiamo fatto qui?
Beh, prima ho chiamato GetString.
E ho memorizzato il valore di ritorno di s.
Ecco, questo è più o meno lo stesso di Questa parte superiore dell'immagine.
>> Ma che cosa viene dopo?
Beh, mi permetta di andare avanti e di sbarazzarsi di un intero gruppo di questo.
Ci Rewind nel tempo per cui abbiamo appena avere s, che ora è in linea con
linea uno lassù.
>> Posso controllare.
Se s è uguale uguale a 0.
Ora, una nota a margine veloce, quando Potrebbe GetString restituire 0?
Non c'è abbastanza memoria.
Giusto?
>> E 'raro che questo sta per accadere, certamente su un computer che è
ottenuto centinaia di mega o anche giga di RAM.
Ma potrebbe, in teoria, il ritorno 0, soprattutto se l'
utente non collabora.
Ci sono modi per far finta che tu non hai immesso nulla e trucco
GetString in ritorno 0 efficacemente.
>> Così sta andando a controllare per questo.
Perché se qualcuno di voi ha iniziato a ottenere, già, segmentation fault -
che è probabilmente stata una fonte di un po 'di frustrazione -
quelli sono quasi sempre il risultato di memoria correlata errore.
In qualche modo incasinato nei confronti di un puntatore, anche se non si rese conto
c'era un puntatore.
Così si potrebbe avere indotto segmentazione difetti fin dalla settimana usando uno
qualcosa di simile a un ciclo for o un po ' loop e un array di andare troppo lontano
oltre i confini di alcuni array che avete dichiarato, in due settimane in
particolare.
>> Si potrebbe avere fatto anche nel problema impostare quattro con Breakout.
Anche se probabilmente non avete visto le stelle del codice di distribuzione per
Breakout, si scopre che quelli GRect e Goval e altre cose del genere,
quelli sono in realtà puntatori sotto la cappa.
>> Ma Stanford, come noi, una sorta di pelli che precisa almeno per le librerie
scopi, tanto come facciamo noi per la stringa e char *.
Ma GRect e Goval e tutti coloro cose che voi ragazzi siete o useranno
Questa settimana sono in ultima analisi, indirizzi di memoria.
È solo che non lo sai.
>> Quindi non è sorprendente allora, forse, che si potrebbe inciampare qualche
segmentation fault.
Ma ciò che è interessante qui ora, se dopo che controlliamo per 0 che facciamo
stringa t ottiene s.
Beh, lasciatemi dichiarare t.
Io vado a disegnare come un quadrato, 32 bit, lo chiamano t.
E poi ho intenzione di fare diventa s.
>> Ebbene, che cosa vuol dire?
Beh, è ​​un po 'difficile pensare su di esso raffigurarsi saggio.
Ma pensiamo a cosa c'è dentro di x?
Cosa c'è letteralmente dentro questa variabile?
Il valore Ox123.
>> Quindi, quando dico stringa t ottiene s, che proprio significa letteralmente prendere il numero
in s, che è Ox123 e metterlo Ox123.
Oppure, pittoricamente, se io tipo di abstract lontano da quel dettaglio ha la
effetto di fare letteralmente questo.
>> Così ora, ripensare a settimana scorsa, quando si è proceduto alla capitalista T.
ha fatto T staffa 0.
Beh, T staffa 0, anche se si tratta di un puntatore, è possibile trattarlo come se
si tratta di un array, con un quadrato notazione staffa.
>> Allora, dove è T staffa 0?
Beh, è ​​l'h.
E così quando usiamo quella riga di codice, due superiori, che è in quella c type.h
file di intestazione, ecco dove viene dichiarata.
Stai capitalizzando questo H. Ma di Naturalmente, questa è la stessa h esatto che è
all'interno di s, per così dire.
E così ora si è modificato o capitalizzati sia l'originale e la
cosiddetti copia.
Perché non hai fatto una copia nella modo che un essere umano vorrebbe che fosse.
>> Così che cosa è stata la correzione qui, in copy1.c scorsa settimana?
Funzioni, quindi in realtà potrebbe copiare la stringa.
E fondamentalmente, ciò che abbiamo bisogno di fare in modo di copiare la stringa?
>> Ebbene, in questa versione verde qui sono intenzione di farlo piuttosto basso livello.
Ci sono in realtà funzioni potrebbero aiutare con questo.
Ma il più semplice ed il più un familiare, almeno, sarà presto
familiare a noi, è la seguente -
così uno sulla prima riga del codice in verde ora.
>> Ho appena riscritto s come char *.
Non c'è funzionale differenza lì.
Ho appena buttato via la biblioteca CS50 e Lo sto chiamando quello che è, un char *.
>> Ora punto, punto, punto, perché ci sono stati qualche controllo degli errori che non
interessante parlare di nuovo.
Così ora t è dichiarato.
Anch'esso è un char *.
Così ho disegnato un piccolo quadrato sulla lo schermo come prima.
>> Ma sul lato destro, malloc, abbiamo detto è la memoria allocare.
Quindi assegnare alcuni pezzo di memoria.
E quanti byte abbiamo effettivamente desidera allocare, ti sembra?
>> Beh, la lunghezza della stringa di s.
Quindi, se è ciao questo è sta per essere cinque.
Diremo h-e-l-l-o.
Così cinque byte.
>> Ma poi più 1, perché 1?
Il carattere 0.
Se non lasciamo spazio a questo ragazzo abbiamo potrebbe creare accidentalmente una situazione
in cui la stringa è h-e-l-l-o.
E poi la prossima volta GetString è chiamato e digito, per esempio,
David, D-a-v-i-d, il computer sta a pensare che s è in realtà
h-e-l-l-o-d-a-v-i-d, perché c'è nessuna rottura tra quelle parole.
>> Quindi abbiamo bisogno che si rompono.
Quindi non vogliamo cinque.
Vogliamo sei byte.
>> E byte mi dicono.
Ma è davvero il momento di dimensione carattere.
Tecnicamente char è quasi sempre un singolo byte.
>> Ma proprio per rendere il nostro codice portabile, così dire, in modo che funzioni su
computer diversi, anche se potrebbe essere diverso sotto l'
cappa, ho intenzione di genericamente dire dimensione del carattere in modo che
il mio codice funziona sempre.
E io non devo ricompilare solo perché aggiorno il mio computer o utilizzare
qualche piattaforma diversa.
>> Così ho 6 volte la dimensione della un char, che risulta essere 1.
In modo che i mezzi malloc potrebbe dammi sei byte.
Che cosa è che effettivamente facendo?
Bene, lasciate rotolare indietro nel tempo qui al punto in cui siamo nella storia.
>> Quindi, se torno qui, ho dichiarato un char * chiamato t.
Ora ho chiamato malloc per sei byte.
E ora vado a disegnare quei sei bytes proprio come la matrice precedente.
Ma io in realtà non so che cosa è all'interno di questa matrice.
>> Se si alloca la memoria si scopre che non ti puoi fidare che c'è qualche
valore noto lì.
Potrebbe essere stato usato da qualcosa altro, qualche altra funzione, qualche altro
riga di codice che hai scritto.
Quindi dovremo generalmente chiamiamo questi spazzatura valori e disegnarli, forse, come
punti interrogativi, proprio ad indicare che abbiamo non so che cosa in realtà è lì.
E questo è un grosso problema fino a quando ci sono abbastanza intelligente per sovrascrivere quelli
valori di immondizia con numeri o caratteri che ci stanno a cuore.
>> Quindi in questo caso cosa posso fare?
Bene, la mia riga di codice prossimo, ho quattro.
INT ottengo 0, n diventa il lunghezza della stringa di s.
Quindi un familiare ciclo for.
I è minore o uguale an, che di solito è al di sopra.
>> Ma questa volta è intenzionale.
I + +, e poi io semplicemente faccio t staffa mi viene s.
Perché la mia immagine si presenta così al questo momento, memorizzate in t è l'
indirizzo di tale blocco casuale di memoria valori di cui sono sconosciuti.
Ma appena faccio t staffa 0 che mi pone qui.
>> E che finisce per essere disegnato lì?
Si finisce per mettere h.
Perché questo è ciò che è in s staffa 0.
E poi la stessa cosa per E e L e L, e o.
>> n, per cui sono andato attraverso un uguale an?
A causa del carattere 0.
Quindi, tanto per essere chiari, allora, se ho effettivamente cancellare qualunque questi spazzatura
I valori sono poi effettivamente disegnare in quello che mi aspetto, questo è s staffa 1, 2,
3, 4, oltre a quello è trailing nuovo personaggio.
>> E così ora, se abbiamo continuato passato il punto, puntini, puntini in questa versione corretta
e capitalizzato t staffa 0 vorrei, di naturalmente essere capitalizzare solo questo
tizio qui, che concettualmente, era, in definitiva l'obiettivo.
Ecco, questo è tutto il puntatore.
>> E hai usato loro per settimane ora nel contesto delle stringhe.
Ma sotto il cofano sono un po 'più complessa.
Ma se si pensa a loro in questo forma pittorica propongo che siano
Probabilmente non tutto quello spaventoso quanto potrebbe sembrare a prima vista, a prima vista,
in particolare con tale nuova sintassi.
Tutte le domande su puntatori, stringhe o salmerini?
Sì?
>> AUDIENCE: Puoi tornare indietro per il [incomprensibile]?
>> SPEAKER 1: Certo.
>> AUDIENCE: Allora come mai nella vostra ultima linea, non si dispone di una linea di t *
e un * s nella linea?
Non avete il riferimento al -
>> SPEAKER 1: Ah, davvero una bella domanda.
Perché non ho un * t ed a * s?
Perché brevemente, la scorsa settimana, come nel nostro funzione swap, ho detto che quando
hai un puntatore il mezzo attraverso il che ci andate come abbiamo fatto noi
fisicamente sul palco, è stato quello di realtà utilizzare l'operatore stella.
>> Si scopre che questo quadrato-fascia notazione è quella che chiameremo sintattica
zucchero, che è solo un modo sexy di dicendo che è notazione abbreviata per
esattamente quello che stai descrivendo.
Ma è un po 'più intuitivo.
E con il rischio di rendere questo sembra più complicato di quanto dovrebbe essere,
ciò che sta realmente accadendo qui è il seguente -
Se dico * t che significa andare a l'indirizzo memorizzato in t.
>> Quindi, letteralmente, se t è la memorizzazione l'indirizzo di tale h
inizialmente, * t mezzi andare qui.
Ora, che cosa t staffa 0 significa?
Stessa cosa esatta.
E 'solo un po' più user amichevole di scrivere.
>> Ma io non ho ancora finito.
Non posso dire * t * s ottiene.
Perché quello che dovrei fare allora?
Sarei mettendo h, h, h, h, h in tutta l'intera faccenda.
Giusto?
>> Perché * t è aprire l'indirizzo in t.
Ma siamo all'interno di un ciclo.
E che valore sto incrementando, ovviamente, ad ogni iterazione?
i.
>> Ma c'è la possibilità qui, giusto?
Anche se questo si sente come si sta facendo un po 'più sofisticato
rispetto alla notazione quadrata staffa abbiamo usato per qualche tempo -
fammi Annulla l'cambiamento h lì -
anche se questo è ora ottenere un po 'di amatore, l'idea di base, se * t
significa qui e * t è solo aprire l'indirizzo in t.
>> Ma quello che era l'indirizzo in t?
Il numero continua a usare?
Come Ox456, cerchiamo di portare indietro solo per il gusto della discussione.
Beh, se voglio arrivare alla posta in stringa t, voglio solo andare a,
essenzialmente, 456.
>> O meglio, 457.
Ho solo bisogno di aggiungere uno.
Ma io posso farlo, giusto?
Perché t, anche se continuo a disegno ora come una freccia, è solo un
numero, Ox456.
E se aggiungo uno a che, o più in generale, se aggiungo io per quello che posso
effettivamente ottenere esattamente dove voglio.
Quindi, se ho fatto fare questo -
e questo è ciò che è ora chiamato l'aritmetica dei puntatori -
Posso rimuovere questa riga.
Il che è, francamente, penso che più chiara e un po 'più facile da leggere.
Ma questo non è meno corretto.
>> Questa linea di codice ora sta usando l'aritmetica dei puntatori.
Sta dicendo che andare al seguente indirizzo -
qualunque sia l'inizio di t è, che è t più ho, che inizialmente
è 0, che è grande.
Perché questo significa l'inizio di t più 1, più 2, più 3, e così via.
E lo stesso affare con s.
>> Zucchero in modo sintattico per questo.
Ma la comprensione di ciò che sta realmente accadendo sotto il cofano, direi,
in realtà è utile in sé e per sé.
Perché significa ora non c'è molto di più la magia succede
sotto la cappa.
Non ci stanno per essere molti di più strati che si possa staccare per voi.
Questo è c.
E questa è la programmazione.
Davvero buona domanda.
>> Va bene, quindi questo è stato che buggy programma mi riferivo prima.
di swap era viziata.
Se sembra funzionare.
Ricordiamo che, proprio come con il latte e il succo d'arancia - che ho iniziato
bere la manifestazione di oggi.
Quindi, proprio come con il succo d'arancia e il latte, abbiamo avuto bisogno di usare una
variabile temporanea, tmp, per tenere un temporaneamente in modo che si potrebbe poi
modificarne il valore e quindi aggiornare b.
>> Ma questa funzione, ci ha detto, o questa programma in cui questa funzione era
scritto era sbagliato e viziata, perché?
Sì?
>> AUDIENCE: [incomprensibile].
>> SPEAKER 1: Esattamente, quando si chiama swap -
o più in generale, quando si chiamare più alcuna funzione -
se gli argomenti a tale funzione sono primitive, per così dire, int e char
e doppie e galleggianti, cose senza stelle, si passa in una copia di
l'argomento.
Quindi se x è 1 ey è stato 2, una sta a 1 e B sta per essere 2.
Ma loro stanno andando a essere diversi pezzi di bit, diversi pezzi di
memoria che capita di essere l'archiviazione valori identici.
>> Quindi, questo codice è super perfetto a scambiare a e b.
Non va bene a scambiare -
nell'esempio della scorsa settimana -
x ed y.
Perché ancora una volta, sono nel campo di applicazione sbagliata.
>> Ora, come abbiamo fatto a fare per risolvere questo?
Abbiamo dovuto fare la funzione di guardare un po 'più brutta.
Ma ancora una volta, considerare ciò che questo significa solo.
>> E in realtà, mi permetta, per coerenza, cambiare una cosa così è identica a
quello che abbiamo appena fatto.
Come ho già detto la scorsa settimana, non lo fa importa dove va.
In realtà, di solito si dovrebbe mettere il stella accanto al nome della variabile.
Ma penso che sarebbe un po 'più facile considerare il * accanto
tipo di dati nel senso che è un puntatore ad un int in questo caso.
>> Allora, cosa ci faccio qui?
Io sto dicendo che non mi danno un int seguito da un altro int,
chiamandoli a e b.
Dammi l'indirizzo di un int.
Dammi l'indirizzo di un altro int.
Chiamare questi indirizzi a e b.
>> E quindi utilizzando la notazione * giù sotto, andare a ciascuno di questi indirizzi
come necessario per ottenere sia o impostare il valore.
Ma c'è un'eccezione qui.
Perché non ho un * accanto al tmp?
Perché non lo faccio, per esempio?
Ci si sente come dovrei solo andare tutti fuori e correggere il tutto.
Sì?
>> AUDIENCE: [incomprensibile].
>> SPEAKER 1: Non ho dichiarato tmp come stringa.
Quindi questo sarebbe dichiarare, in questo caso, un tmp di essere l'indirizzo di un int.
Ma non è tutto quello che voglio, per un paio di motivi.
>> AUDIENCE: Non si vuole per scambiarle.
>> SPEAKER 1: Esatto, io non voglio scambiare nulla con tmp. tmp è solo
settimana-una roba.
Tutto quello che voglio è una variabile per memorizzare qualche numero.
Non ho nemmeno importa di indirizzi in questo momento.
>> Ho solo bisogno di 32 bit o modo per memorizzare un int.
E voglio mettere in quei 32 bit tutto ciò che non in una, per così dire, ma
ciò è ad una, solo per essere più precisi.
Perché se a è un indirizzo, * un mezzo andare lì e ottenere il valore 1.
Ad esempio, nell'esempio della scorsa settimana o in caso di B, ottenere il valore di 2.
>> Così che cosa sta realmente accadendo?
Permettetemi di fare un disegno che qui si solo prendere in giro a parte parte di oggi.
Ma questo continuerà ad apparire per un bel po 'di tempo.
>> Questo, io sostengo, è ciò che il computer di memoria appare come quando si esegue un
programma, qualsiasi programma.
Quando si esegue un programma in cima della RAM del computer - in modo da pensare di
questo rettangolo, veramente, come il tuo RAM o della memoria del computer, tutti i 101
miliardi di byte di esso, tutto due miliardi byte, tutti i due gigabyte di esso,
qualunque sia la quantità che hai è, Impara a disegnare come un rettangolo.
E io sostengo che quando si esegue un programma come Microsoft Word o Chrome
o qualcosa di simile, i bit che Microsoft o che Google ha scritto -
nei casi di quei programmi -
vengono caricati nella memoria del computer dove possono essere eseguiti più
rapidamente ed immessa nella CPU, che è il cervello del computer.
>> E in TAM ma sono archiviati per lo superiore del vostro programma, per così dire.
In altre parole, se questo è un pezzo di memoria, quando si fa doppio clic su
Microsoft Word, i bit vengono fuori il disco rigido.
Essi vengono caricati nella RAM.
E faremo tirarle fino in cima di questo rettangolo concettualmente.
>> Beh, il resto della vostra memoria è usato per cose diverse.
Nella parte superiore si vede inizializzare dati e Uninitialize dati.
Questo ha a che fare, per la maggior parte, con costanti o variabili globali
che hanno valori.
Ma più su quelle un altro tempo.
>> Allora avete il mucchio, che torneremo a.
Ma sul fondo è la parte che è particolarmente germano momento.
È il cosiddetto stack.
Quindi, proprio come nella maggior parte qualsiasi sala D qui su campus, avete quei vassoi che
basta impilare uno sopra l'altro su cui si può mettere il cibo e quant'altro.
Lo stack in un sistema informatico è molto simile.
Tranne mentre il vassoio, come si usa in la sala da pranzo, naturalmente, si intende
per portare le cose i vassoi o le cornici -
come li chiameremo - in un computer di memoria è utilizzato per contenere
variabili e valori.
>> Quindi, cosa succede veramente sotto il cofano?
Beh, mi permetta di capovolgere alla schermata qui.
E concentriamoci solo sul parte inferiore per un momento.
Se questa è la porzione di fondo della mia memoria del computer si scopre quando ho
chiamare la funzione principale - che avviene, francamente,
automaticamente per me -
Ho un pezzo di memoria al profondo del mio RAM per così dire.
Ed è qui che principale di variabili locali vanno.
E 'dove argc e argv forse andare, e le eventuali variabili di I
dichiarare all'interno del principale.
Finiscono in fondo di RAM del mio computer.
>> Ora supponiamo che i principali chiama una funzione come swap, come ha fatto la settimana scorsa?
Beh, abbiamo essenzialmente messo un nuovo vassoio, un nuovo telaio, sul mio pezzo di memoria.
E ho intenzione di descrivere questo come appartenente alla funzione swap.
>> Ora cosa c'è dentro di swap?
Ebbene, sulla base del programma della scorsa settimana e quello che abbiamo appena visto un estratto,
all'interno della struttura di swap, o scambio di vassoio, sono ciò che le variabili?
Beh, a e b.
Perché quelli erano i suoi argomenti locali, più un terzo, tmp.
Quindi, in realtà, ho potuto disegnare questo un po 'più pulito.
Lasciami andare avanti e annullare l'etichetta.
E mi permetta di affermare che si sa che cosa?
>> una è probabilmente andando a finire qui.
B sta per finire qui.
E tmp sta per finire qui.
Ora, il giudice potrebbe essere un po 'diverso.
Ma concettualmente questa è l'idea.
>> E proprio collettivamente, questo è ciò chiameremo cornice di swap, o
vassoio refettorio.
E lo stesso affare con il principale.
Ma non voglio che ridisegnare.
Ma è qui che argc e argv e qualsiasi delle sue variabili locali come x e y
potrebbe essere pure.
>> Così ora prendere in considerazione ciò che sta realmente accadendo quando si chiama swap.
Quando si chiama swap, codice in esecuzione come questo, si sta passando, nel
versione buggy, a e b come copie di x e y.
Quindi, se io ora traggo questa sullo schermo -
avuto modo di arrivare meglio a questo -
così la storia che stavo dicendo a me stesso fu in questa versione buggy, quando abbiamo
Inversione di chiamata passando letteralmente a e b come numeri interi, cosa sta realmente accadendo?
>> Beh, quello che sta succedendo davvero è questo.
Lasciami andare avanti e annullare solo per chiarire un pò di spazio qui.
Quindi questa è la memoria del mio computer.
>> Quindi, se ho, per esempio -
in realtà cerchiamo di fare in questo modo -
se io sostengo che questo è x, la memorizzazione il valore 1, proprio come la settimana scorsa.
E questo è y, memorizzare il valore 2 proprio come la settimana scorsa.
E questa è la principale, quando chiamo swap, dando così accesso a un me e
b, tmp, ho intenzione di affermare che questa è una e questo è 1.
>> Questo è b.
Questo è 2.
Questo si chiama tmp.
>> Ed inizialmente, ha un certo valore spazzatura fino a quando ho effettivamente memorizzare in una,
che è 1.
Poi vado avanti e cambiare una di essere ciò?
Valore di B.
>> E così ora ho due qui.
E poi ci siamo detti b ottiene tmp.
Ancora una volta, proprio come un controllo di sanità mentale, il terzo riga di codice qui è semplicemente questo
uno, B ottiene tmp.
>> E così, infine, che cosa devo fare?
Io vado avanti e cambiare B per essere qualunque cosa il valore di tmp è, che è 1.
Non tocco nuovo tmp.
>> Ma ora, il problema è più presto di swap ritorna, perché non è che distribuiscono
eseguire un certo valore, non c'è ritorno dichiarazione esplicitamente in essa.
Che cosa sta realmente accadendo?
Beh, essenzialmente tutta questa memoria -
OK, a quanto pare la gomma piace un solo dito alla volta -
semplicemente scompare.
>> Ora, in realtà, non è va da nessuna parte.
Ma si può pensare di esso ora come punti interrogativi.
Perché non è più realmente in uso.
E non si fa nulla con quei valori.
>> Quindi, nel caso della versione verde questo codice, quello che invece è essere
passato in swap?
Così indirizzi.
Quindi l'indirizzo di x e l'indirizzo di y.
Quindi, se noi ri-raccontare questa storia un ultimo tempo, e io in realtà traggo ancora swap,
ma con puntatori, essendo questa una, questa essendo b, e questo essere tmp, ciò che è
effettivamente memorizzati in una in questo verde versione del mio codice dove sto passando
in indirizzi?
>> Sta andando essere un puntatore a x.
Così ho potuto disegnare una freccia.
Ma usiamo la stessa arbitraria esempio di prima.
Diciamo che questo è qualcosa come Ox123.
E questo sta per essere Ox127 perché si tratta di quattro byte di distanza perché è un
int, così Ox127.
>> E di nuovo, mi sto prendendo qualche libertà con i numeri.
Sono molto più piccolo di quello che sarebbe effettivamente e in un ordine diverso.
Ma è così che l'immagine ora è diverso.
>> Ma quando uso questo codice verde e io int tmp ricevo * a.
* Un mezzo per fare la seguente, prendere la affrontare che è in una e andare ad esso,
che è 1.
Ed è quello che ho poi messo in tmp.
Nel frattempo, nella riga successiva di codice qui, * una ottiene b, che cosa significa?
>> Beh, * a, in modo da andare qui ottiene * b, che significa andare lì.
E questo significa mettere il valore a lì.
Infine, l'ultima riga di codice semplicemente detto * b ottiene tmp.
>> Quindi b dice di andare lì e sovrascriverlo con tmp che, in questo caso, sta
essere, nuovamente, 1.
Ed è per questo che la versione verde di le nostre opere di codice, mentre il rosso
versione non ha mai fatto.
Tutto solo si riduce a come il la memoria è gestita e dove è
effettivamente immesso nel vostro RAM del computer.
E per ora, questa è una delle cose che lo stack viene utilizzato per.
>> Domande sul layout?
Su puntatori?
O su swap?
>> Va bene, allora malloc, richiamo, ha fatto qualcosa di simile.
Questo è stato un super semplice esempio.
E questo era quello che Binky ci ha presentato, anche se piuttosto
rapidamente, al termine della classe.
Dannazione, non ci siamo di nuovo.
>> Quindi ricorda che questa era l'esempio che Binky ci ha presentato, sia pure
alquanto rapidamente a fine classe.
E qui abbiamo utilizzato malloc davvero per la seconda volta.
Perché la prima volta che abbiamo usato per creare abbastanza RAM, allocare abbastanza memoria RAM
per memorizzare una stringa.
>> Questa volta Binky teneva semplice.
Quindi è per memorizzare solo un int, a quanto pare.
E questo è tutto bene.
E 'un po' strano, francamente, a utilizzare malloc per allocare un int.
Ma il punto di claymation di Nick era in realtà solo raccontare la storia di ciò che
accade o non accade quando vi maltrattano memoria.
>> Quindi in questo caso, questo programma ha fatto un paio di cose.
Nel primo caso qui, dichiara un puntatore chiamato x ad un int.
E poi dichiara un puntatore chiamato y ad un int.
Quindi memorizza in x, che cosa?
Qualcun altro adesso.
Ciò che viene memorizzato in x secondo la terza linea di questo programma?
>> AUDIENCE: [incomprensibile].
>> SPEAKER 1: Beh, non proprio byte, per dire.
Essere più preciso ora.
Ciò che viene memorizzato in x?
Un indirizzo, penso che l'ho sentito.
>> Così che cosa malloc restituisce?
malloc alloca comportamentale un pezzo di memoria.
Ma come fa a dare l'accesso ad esso?
Esso restituisce cosa?
L'indirizzo del primo byte nel pezzo di memoria.
>> Ora, questo è super semplice.
E 'solo un byte, il che significa che la rivolgiamo stiamo tornando è il
indirizzo di tutta la faccenda.
Così memorizzato in x, allora, è l'indirizzo di quel pezzo di memoria.
Nel frattempo, che cosa succede dopo?
Quindi, in realtà, andiamo avanti e disegnare questo fuori in fretta.
>> Quindi, se andiamo oltre alla schermata qui e giochiamo questo fuori int * x e int * y
sta per fare che cosa per me?
Io sostengo che è solo andare a fare qualcosa di simile a questo e lo chiamano x, e
questo e chiamano a.
Nel frattempo, la terza riga di codice è andando ad allocare le dimensioni di un int,
che risulta essere - scusate se ho detto uno prima volevo dire uno int -
quattro byte su un computer tipico.
Almeno con l'apparecchio CS50.
>> Quindi questo sta per allocare si, chi lo sa?
Da qualche parte qui.
E questo è memorizzato in qualche Indirizzo Bue, chi lo sa?
Ma quello che sta per ottenere tornato è tale indirizzo.
Ma noi disegneremo questo pittoricamente come solo una freccia simile.
>> Ora, nella riga successiva * x diventa 42.
Che cosa significa * x significa in parole povere?
Basta andare lì.
Vai a questo indirizzo.
O in altre parole, seguire la freccia e mettere 42 lì.
Ma poi è successo qualcosa di brutto a Binky, giusto?
>> Ricordiamo che la linea di cinque qui, * y ottiene 13, in effetti un numero sfortunato,
fatto quello che per noi?
Bene, * mezzi y ci vanno.
Ebbene, questo non è stato dato ancora un valore, giusto?
Il codice non deve essere y inizializzato a nulla.
Avevamo x essere inizializzato ad un indirizzo.
Ma y è stato dichiarato fino in alto.
Ma poi un punto e virgola, senza valore è stato effettivamente messo in esso.
Quindi è giusto chiamare questa un valore spazzatura.
Chi sa che cosa è?
Sono i resti di bit che sono stati utilizzati da qualche riga di codice precedente in
il mio programma.
>> Quindi, se io dico andare lì, questo è come, Non ho idea di dove questa freccia è
andando a finire.
E che quando in genere si ottenere un errore di segmentazione.
Se accidentalmente dereferenziare, per così parlare, o andare a un indirizzo che non è
in realtà un indirizzo legittimo, succedono cose brutte.
>> E questo è esattamente quello che è successo pensare Binky.
Quindi, ricordare che la storia che Nick era raccontando qui era la stessa idea che cosa
Ho disegnato con l'illusione di gesso sulla lavagna c'è.
X e Y sono dichiarate.
>> Poi abbiamo assegnato la dimensione di un int e memorizzato in x.
Poi la linea successiva abbiamo fatto * x.
Questa è stata la bacchetta magica di Nick di dereferencing.
Che ha messo 42 nella memoria sottolineato da x.
>> Ma questo è dove le cose è andato terribilmente storto.
Giusto?
Abbiamo cercato di risolvere il riferimento a.
Ma y ha un valore falso, giusto?
>> Quella freccia in basso a sinistra angolo, non è
in realtà punta a nulla.
È un po 'a fare quello che fatto qui sulla scheda.
Quindi le cose brutte accadono, segmentazione guasto oppure Binky guasto, in questo caso.
>> Ma se poi fissiamo che facendo x ottiene y come cambia la storia?
Beh, se lo faccio x diventa y, che è effettivamente lo stesso che dire
qualunque cosa sia, Ox-qualcosa sta per essere lo stesso qui,
Ox-qualcosa.
O pittoricamente faremo disegnare una freccia.
>> Così qui sul bordo con Binky, con la prossima linea di
codice, * y significa andare lì.
Dove si trova lì?
Significa qui.
>> E quando ci aggiorniamo che per essere 13 si tratta solo andando e
scrivere 13 qui ora.
Quindi, forse non del tutto semplice a prima vista.
Ma per ricapitolare e di utilizzare lo stesso gergo Binky che stava usando qui, quindi
le prime due assegnano i puntatori, x e y, ma non le pointees.
E pointees non è un generalmente termine usato.
Ma puntatore assolutamente è.
Ma è quello che è stato sottolineato a nella nomenclatura di Binky.
>> Questo successiva linea, naturalmente, alloca un pointee int.
Così un pezzo di memoria - come ho disegnato sopra il il lato destro c'è - e insieme
x uguale per puntare a esso.
Questo dereferenzia x per memorizzare 42 in la memoria che sta indicando.
E poi questo, naturalmente, era una cosa negativa.
Poiché y non puntava a ancora nulla.
Questo lo ripara.
Quindi, questo è ancora programma bacato.
Proprio perché stiamo soffia attraverso la codice riga per riga e dire, oh, va bene,
lasciarlo lì in crash.
Questa è una brutta cosa.
Le probabilità sono il programma è solo andare a interrompere del tutto a quella linea.
Ma se si dovesse rimuovere il schiantato Line e sostituirlo con le ultime due
Linee lì assegnate -
con assegnazione puntatore - y per puntare a x come punto t.
E poi si dereferenziare y in un modo molto sicuro.
>> Perché allora questa ci lascia?
Ebbene, risulta che sotto il cofano nella biblioteca CS50, i puntatori sono
utilizzati in tutto.
E saremo effettivamente iniziare a sbucciare indietro quello strato in breve tempo.
Ma si scopre troppo, un'espressione che alcuni di voi potrebbero avere familiarità con,
particolare quelli più comodo, è in realtà quella di una molto popolare
sito web, oppure un overflow dello stack, in questi giorni.
>> Ma questo è in realtà molto significato tecnico.
Ora sappiamo che cosa è una pila.
E 'come una pila di vassoi all'interno di una sala da pranzo.
>> O all'interno del vostro computer memoria its quei fotogrammi
che vengono utilizzati dalle funzioni.
Bene, si scopre che a causa di questo molto semplice implementazione
memoria e le cornici sulla cosiddetta Catasta, si può effettivamente prendere il controllo
di un sistema di computer abbastanza facilmente.
Si può incidere in un sistema se la gente come noi non abbiamo scritto il nostro codice
particolarmente bene.
>> Se la gente come noi usano pezzi di memoria o di utilizzare matrici -
ancor più comunemente -
ma a volte dimenticare di controllare il confini della nostra gamma come si potrebbe
Lasciati a volte, e iterata troppo lontano oltre la fine di un array.
Nel migliore dei casi, il tuo programma potrebbe anche bloccarsi.
Errore di segmentazione, tipo di imbarazzante.
Non eccezionale, ma non è necessariamente una cosa estremamente negativa.
>> Ma se il vostro programma è in realtà il vero computer degli utenti, se è in esecuzione
su un sito web che le persone casuali reali su internet stanno colpendo, lasciando
inducono le persone brutte cose sul tuo codice è generalmente non è una buona cosa perché
significa l'occasione per fare controllo del computer.
E questo sta a guardare un po 'criptico.
Ma ho pensato di spaventare voi con questo ultimo esempio qui.
>> Ecco un esempio di codice.
E c'è una buona Wikipedia articolo che cammina attraverso
più in dettaglio.
Ho principale sulla vocazione fondo pippo, passando argv di 1.
E questo è solo così che si può eseguire il programma e passare
un ingresso arbitrario.
>> E poi pippo è dichiarata fino in alto come accettare una stringa, o più
appunto, un char *.
E poi dichiara un array di caratteri.
Chiamare un tampone, più in generale, di dimensione 12.
Quindi 12 caratteri può essere contenuto in di tale matrice chiamata c.
>> E poi utilizza questa nuova funzione, che è nuovo, ma non è difficile da
capire, copia della memoria.
Si copia la memoria da bar, che era passato n variabile, qualunque sia la
utente digitato in argv 1 in c.
Quanti byte?
La lunghezza della stringa di bar.
>> Quindi, in altre parole, se l'utente digita in h-e-l-l-o ENTER, la lunghezza della stringa
di ciao è cinque.
Così cinque di quei byte sta per arrivare copiati nella matrice denominata c, che
è di taglia 12.
Ma ciò che l'utente digita in un molto più lungo parola che è 13 caratteri o 14
caratteri o 100 caratteri o più?
>> Dove stanno andando andare?
Beh, questo telaio, che vassoio nello stack refettorio,
hanno intenzione di andare lì.
Ed è solo andare per iniziare la sovrascrittura altra roba che è già
su quella pila, traboccante la pila, per così dire.
>> Così pittoricamente, pensare in questo modo.
Questa è solo una versione colorata di la foto abbiamo attirato.
In fondo, diciamo, è il principale.
E in alto, quello che stai vedendo ora è il telaio, il colore codificato ora, per un
funzione chiamata foo.
Ma ciò che è interessante circa foo è che qui è la sua cornice.
Così è disegnato proprio come ho fatto ma in azzurro.
E ora è qui c staffa 0 va.
Ed è qui che staffa c 11 sta per finire.
>> In altre parole, succede a essere rappresentato come un quadrato.
Ma se continui plopping bytes giù - o caratteri - che stanno andando a finire
fino alla posizione 0 tutta la strada fino a 11 perché è 0 indicizzato.
>> Ma dove è il carattere 13 andando a finire?
Dov'e 'il 14?
Dov'è il carattere 50 ° andando a finire?
>> E 'intenzione di continuare ad andare giù.
Perché anche se abbiamo disegnato la foto con la pila cresce, il
indirizzi, si scopre, vanno da piccole indirizzi, piccolo
puntatori, ai grandi indirizzi.
Quindi continua a andare su e su.
>> Quindi, se l'utente digita in ciao, che è grande.
Nessun problema, nessun problema, sicuro di tutti.
Ma se l'utente digita in quello che faremo chiamare codice contraddittorio, rappresentato
genericamente come, attaccare, attaccare, attaccare, attaccare, cosa può succedere?
>> Ebbene, se tutto l'input che l'utente digitato non è solo qualche amichevole
o una stringa di caratteri offensivo.
In realtà è una sequenza di caratteri che se è stato compilato,
in realtà è il codice.
Forse è il codice che elimina tutte le file sul disco rigido o invia lo spam
o qualcosa di simile.
Si noti che ciò che è fondamentale è che Se il cattivo avuto la fortuna di
sovrascrivere il pezzo rosso della memoria -
che non ho disegnare sulla mia immagine, ma Wikipedia questa immagine qui ha -
il suo cosiddetto indirizzo di ritorno.
>> Quando ritorna cibo, quando ritorni swap, come fa il computer a sapere di andare da
qui a qui?
O nel segmento tecnologico in alto, come fa a sapere di andare allo swap
codice - il 0 e di 1 che compongono swap -
torna alla pagina principale?
C'è un cosiddetto indirizzo di ritorno memorizzato in quello stesso stack frame, il
la stessa caffetteria cassetto.
>> Quindi, se il cattivo è abbastanza intelligente da inserire il codice di attacco, il codice di attacco, attacco
codice, e ottenere la fortuna -
spesso attraverso tentativi ed errori - per sovrascrivere l'indirizzo di ritorno rosso,
con l'indirizzo e la comunicazione la cima.
Notate 0835C080.
E 'scritto a ritroso fino in alto per ragioni che faranno forse rivisitare.
Questo è quel numero.
>> Quindi, se il cattivo diventa abbastanza fortunato o è abbastanza intelligente per sovrascrivere il rosso
striscia di memoria con l'indirizzo del codice che lui o lei ha in qualche modo
iniettato nel vostro computer, indovina il cui codice sta per essere restituito al
appena pippo viene fatto eseguendo?
>> Codice del cattivo.
Quindi questo codice attacco, AAA, ancora una volta, potrebbe inviare spam, potrebbe eliminare tutti i file
sul disco rigido.
Ma questo è ciò che veramente un overflow dello stack è, o un sovraccarico del buffer, o di un
Buffer overflow.
>> Ed è incredibilmente, incredibilmente comune a questo giorno con programmi scritti in
C, C + +, e anche alcune altre lingue.
In tale nota spaventoso, faremo terminare con una battuta.
>> [Risata]
>> Ci vediamo il Mercoledì.
Al prossimo CS50 -
Quindi sono tutti fuori di lampade disco oggi, ma aspettare, senza grassi del latte, la metà del telefono
libro, il succo d'arancia che ho bevuto oggi.
Cavo USB, una chiave inglese.
>> [MUSIC PLAYING]