[MÚSICA DE JOGO]
>> DAVID J. MALAN: Tudo bem.
Este é CS50.
E este é o início da semana 5.
E como você deve ter notado, parte do material
está ficando um pouco mais complexo, a pouco mais denso.
>> E é muito fácil, especialmente se você foi o hábito há algum tempo,
estar tentando rabiscar mais tudo o que fazemos, nós estamos dizendo na sala de aula.
Mas perceber, que talvez não seja a abordagem pedagógica ideal
para aprender esse tipo de material, e material de um modo mais geral.
E assim temos o prazer de anunciar própria Gheng desse CS50
Gong começou a se preparar um conjunto canônico de notas
para o curso, a esperança da que é que, uma, estes
não só servir como um referência e um recurso
para material de revisão e vai de volta através do material que pode ter
escapou-lhe a primeira vez, mas também para que suas cabeças podem ser mais
-se que para baixo, quando chega a hora de palestra,
de modo que você pode se envolver mais pensativo, como
oposição ao mais scribbly.
>> Com o que disse, o que você vai encontrar em o site é documentos como este.
E observem, no canto superior esquerdo, há não apenas uma tabela de conteúdo,
mas também códigos de tempo que será imediatamente saltar você
para a parte apropriada no vídeo online.
E o que Chang fez aqui é, essencialmente, documentado
o que aconteceu neste especial de palestras.
E muitas das palestras são Já estão online agora com este URL.
E vamos continuar a postar o restante daqueles até o final desta semana,
por isso tirar proveito desse recurso.
>> Assim, sem mais delongas, começamos a descascar
a camada que tem sido cadeia por algum tempo.
E o que dizemos uma string na verdade é da semana passada?
Então, estrela de char.
E Char estrela, bem, o que que isso realmente significa?
Bem, todo esse tempo, se nós foi chamada de uma função,
como getString, e armazenamento o retorno chamada
valor de getString numa variable-- é chamado
s tipo string-- que tenho escrito a linha de código lá em cima.
E é só quando eu ver o meu caligrafia ampliada aqui
eu perceber o quão atroz que é isso.
>> No entanto, vamos supor que, no lado da mão direita
é, no entanto, uma razoável representação do que é
vem acontecendo tudo isso tempo com getString.
getString, é claro, fica um string.
Mas o que isso realmente significa?
Isso significa que ele fica um pedaço de memória do sistema operacional
chamando uma função, chamada malloc.
Mas mais sobre isso mais tarde.
E então ele preenche que pedaço de memória
com as letras que o usuário tem digitei, seguido de, é claro,
um caractere nulo, ou barra invertida zero no final.
>> Enquanto isso, no lado esquerdo desta história, todo esse tempo,
temos vindo a declarar uma variável, como s.
E essa variável é o que agora vai começar a chamar um ponteiro.
Não é uma caixa dentro da qual colocamos a corda, Daven, por si só,
mas nós colocamos naquela praça caixa à esquerda o que exatamente?
Sim?
>> AUDIÊNCIA: O endereço de onde ele está localizado na memória.
>> DAVID J. MALAN: Exatamente.
O endereço de onde Daven está localizado na memória.
E não onde todos Daven está localizado, de per si, mas especificamente o endereço
de quê?
Sim?
>> AUDIÊNCIA: Primeiro personagem.
>> DAVID J. MALAN: O primeiro caractere em Daven, que, neste caso,
I proposto foi arbitrariamente e irrealisticamente 1, OX 1,
o que significa apenas o número hexadecimal de 1.
Mas provavelmente vai para ser um número muito maior
que poderíamos chamar com um 0x como um prefixo,
representando um personagem hexadecimal.
E porque não precisamos de saber onde o resto dos personagens de Daven
são, por causa do que design simples decisão que foi tomada há muitos anos?
Sim?
>> AUDIÊNCIA: Barra invertida 0.
DAVID J. MALAN: Sim, exatamente.
A barra invertida 0 permite-lhe, ainda que de tempo linear, para atravessar a corda,
a pé da esquerda para a direita, com um loop, ou um tempo
loop, ou algo parecido que, e determinar, oh, aqui
é o fim dessa seqüência particular.
Assim, com apenas o endereço em o início de uma string,
podemos acessar a totalidade de , porque todo esse tempo,
uma seqüência tem sido apenas uma estrela de char.
>> Por isso, é certamente bem para continuar a utilizar a biblioteca CS50 e essa abstração,
por assim dizer, mas vamos começar a ver exatamente
o que está acontecendo debaixo de todo este tempo.
Então você pode recordar este exemplo, também, a partir da última vez, comparar 0,
que não chegou a comparar.
Mas começamos a resolver isso.
>> Mas como, talvez, uma reciclagem, Eu poderia interessar alguém
em um elefante rosa de hoje, também feita por Chang?
Que tal você na frente? [Inaudível].
Vamos lá para cima.
>> E nesse meio tempo, como você venha, vamos
considerar por um momento o que este código foi realmente fazendo.
É declarar duas variáveis ​​se top, s e t, e chamando getString.
Este não é um programa de fácil utilização, porque não lhe diz o que fazer.
Mas vamos supor que estamos focando a parte suculenta.
E então, o que fazemos, se s é igual a é igual a t, ele deve dizer printf,
você digitou a mesma coisa.
Olá.
Qual o seu nome?
>> JANELLE: Janelle.
DAVID J. MALAN: Janelle, prazer em conhecê-lo.
Portanto, o seu desafio no mão para este elefante
é a primeira a chamar-nos um retrato do que está sendo representados naqueles dois primeiros
linhas.
Assim, s e t pode ser representado como na tela?
E você pode apenas desenhá-lo com seu dedo na tela grande.
>> Portanto, há duas metades para cada lado da equação.
Portanto, não há s à esquerda, e então GetString à direita.
E depois há t do lado esquerdo, e, em seguida, GetString à direita.
Então, como podemos começar fazer um desenho que
representa o que está acontecendo aqui na memória, você diria?
E deixe-me deixá-lo explicar o que você está fazendo que você vá.
>> JANELLE: OK.
Bem, em primeiro lugar, ele estaria pedindo você para obter a seqüência de entrada.
E seria store-- oh, sinto muito.
DAVID J. MALAN: OK.
Boa.
E isso é chamado de quê?
Oh, OK.
Continue.
Eu não queria interromper.
JANELLE: Desculpe.
Por isso, seria introduzi-lo em o endereço não de-- certeza.
Não me lembro exatamente o número, mas eu acredito que foi a partir de 0.
>> DAVID J. MALAN: Está tudo bem, porque eu fiz os números acima,
por isso não há resposta certa.
>> JANELLE: Começando com a 0 arco.
>> DAVID J. MALAN: OK, então o elemento 0.
Claro.
>> JANELLE: E então se foi como apenas um dois-letter--
>> DAVID J. MALAN: OK, de volta para você.
>> JANELLE: Então o elemento 0, e em seguida, um elemento ou elemento 2.
DAVID J. MALAN: E qual parte do a imagem que você está desenhando agora?
A chamada para getString?
Ou a declaração de s?
>> JANELLE: A declaração de s, eu acredito.
Oh, o getString, porque seria ser introduzido em cada um [? área. ?]
>> DAVID J. MALAN: Good.
Exatamente.
Mesmo que isso efetivamente retorna um array, recall,
quando voltarmos uma string, podemos índice para essa string usando 01 e 2.
Tecnicamente, estes são, provavelmente, representado por endereços individuais,
mas isso é bom.
>> Então suponho que, se eu puder apenas rápido encaminhar para onde paramos
última vez que, se um de as cordas era g a b e,
barra invertida 0, representando assim Gabe entrada, como podemos representar s agora?
Se esta é a memória que está foram devolvidos por getString?
>> JANELLE: Seria representado por um arco?
>> DAVID J. MALAN: por um arco?
Bem, não.
Vamos apenas dizer que, pictoricamente, deixe-me ir em frente
e propor que, se isso é s, esta é o valor de retorno de getString.
E você desenhou isso como 0, 1, 2, que é perfeitamente razoável, porque nós
pode indexar na seqüência, como tal.
Mas apenas para ser consistente com última vez, deixe-me ir em frente
e arbitrariamente propor que esta é o endereço 1, este é o endereço 2,
este é o endereço 3, e assim por diante.
E assim, apenas para ser super claro, o que está acontecendo
ir no s como um resultado de que primeira linha de código, você diria?
>> JANELLE: Endereço 1?
>> DAVID J. MALAN: Exatamente.
Assim, abordar 0x1.
E enquanto isso, deixe-me ir em frente e duplicar muito do que você fez
e adicionar o meu próprio t aqui.
Se eu fosse para digitar gabe de novo, uma segunda vez,
quando solicitado com getString, onde, é claro, é gabe vai?
Bem, presumably--
>> JANELLE: Como aqui?
DAVID J. MALAN: Yeah.
JANELLE: Ou é também nas mesmas caixas?
DAVID J. MALAN: Deixe-me propor, sim, exatamente, por isso, nessas caixas adicionais.
Mas o que é fundamental, agora, é que, mesmo embora eu desenhei estas bem perto
together-- 0x1, este é 0x2-- na realidade,
isso agora pode ser o endereço 0x10, por exemplo, e de 0x11, 0x12 e,
e assim por diante.
E assim, se esse for o caso, o que vai acabar por aqui em t?
>> JANELLE: 0x10?
DAVID J. MALAN: Exatamente.
Então 0x10.
E agora, a pergunta final.
Você tem, de longe, tinha que trabalhar a mais difícil para um elefante até o momento.
Até agora, se eu puxar para cima o código mais uma vez, quando eu faço, na linha de três,
se s é igual a igual t, o que eu sou, na verdade, comparando que temos desenhado aqui?
>> JANELLE: Os dois endereços?
DAVID J. MALAN: Exatamente.
Então, eu estou dizendo é S igual igual at?
Em outras palavras, é um igual igual a 10?
E, evidentemente, o resposta óbvia é agora, não.
E assim, este programa é, em última análise vai imprimir o quê, você diria?
>> JANELLE: Seria, você digitou a mesma coisa?
>> DAVID J. MALAN: Então, se s representa 1 e t é 10?
>> JANELLE: Escreveu coisas diferentes.
>> DAVID J. MALAN: Exatamente.
Você digitou coisas diferentes.
Tudo certo.
Então, uma salva de palmas, se pudéssemos, aqui.
[Aplausos]
Isso foi doloroso.
Eu sei.
Muito bem feito.
Então agora vamos ver se não podemos desmembrar o que a correção era.
E, claro, quando se fixa isso-- que agora vai representar em green--
fizemos algumas melhorias aqui.
Em primeiro lugar, assim como uma sanidade verificar, estou verificando primeiro
se s é igual a nulo e t é igual a null.
E só para ficar claro, quando pode s ou t ser nulo no código como este?
Quando S ou T pode ser nulo.
Sim?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Exatamente.
Se a seqüência de caracteres que o usuário digitado é um caminho muito longo
para caber na memória, ou algum caso canto estranho assim,
getString, como veremos, literalmente hoje, em sua documentação,
diz que vai retornar nulo como um valor de sentinela especial,
ou apenas uma espécie de símbolo especial isso significa que algo deu errado.
Por isso, queremos verificar se há que, pois verifica-se
que nulo é um valor muito perigoso.
>> Muitas vezes, se você tentar fazer algo com nulo envolvendo um function-- passá-lo
como entrada, para que a função instance-- pode muito vai bater e, com ele,
derrubar todo o seu programa.
Portanto, esta terceira linha agora é apenas uma sanidade cheque, verificação de erros, se você quiser.
Isso é um bom hábito agora para nos para entrar em qualquer momento que
tente usar um valor que poderia, potencialmente, ser nulo.
>> Agora, na quarta linha aqui, "Se strcmp (s, t)," bem,
o que é que se refere?
Bem, disse que esta era uma forma muito sucinta função chamada para comparação de strings.
E o seu propósito na vida é comparar seu primeiro argumento contra ela em segundo lugar,
mas não em termos de seus endereços, como fizemos involuntariamente um momento
atrás com o código vermelho, mas em vez de comparar os dois
cordas no humanamente intuitiva forma, comparando este, contra este,
contra isso, contra isso, e em seguida, parar se e quando um
ou ambos os dedos atinge uma barra invertida 0.
Strcmp Então anos atrás alguém implementado implementar para nós a funcionalidade
que esperávamos, teríamos conseguido por apenas dois valores de comparação simples.
>> Agora, francamente, eu continuo desenho todos estes vários números.
Mas a realidade é, eu estive tornando-os para cima o tempo todo.
E então deixe-me ir em frente e rabiscar estes para fora
fazer um ponto em que, no final do dia e seguir em frente,
nós não estamos indo realmente se preocupam com que aborda as coisas são, na verdade,
na memória.
Então eu não vou desenhar estes tipos de números muito mais,
Eu sou apenas um resumo este fora um pouco mais amigável com apenas flechas.
>> Em outras palavras, se s é um ponteiro, Bem, vamos apenas desenhá-lo, literalmente,
como um ponteiro, uma seta apontando para de si mesmo para outra coisa,
e não se preocupar muito mais sobre as minúcias desses endereços
que, mais uma vez, eu fiz de qualquer maneira.
Mas vamos ver os endereços, às vezes, quando a depuração do código.
>> Agora, entretanto, este programa aqui correções, é claro,
problema que comparando essas duas cordas.
Mas nós funcionamos em outro problema.
Esta foi a partir da cópia programar última vez,
segundo o qual, eu estava tentando capitalizar apenas o primeiro caractere em uma string.
Mas o que era o sintoma vimos da última vez, quando
um usuário digitou um valor, como gabe em minúsculas, para s,
então atribuído s em t, tal como na terceira linha não,
e então eu tentei capitalizar t suporte 0?
Qual foi o efeito de mudando t suporte 0 aqui?
>> AUDIÊNCIA: Mudou s.
>> DAVID J. MALAN: Sim, Mudei s, também.
Porque o que realmente estava acontecendo?
Bem, deixe-me ver se eu consigo limpar esta imagem, como se segue.
>> Se s for, outra vez, a palavra g, A, B, E, barra invertida, 0 e s
vamos continuar a desenhar como uma caixa aqui, mas não mais endereços.
Vamos parar de fazer as coisas.
Vamos apenas fazer um desenho para simplificar o mundo.
>> Quando eu declaro t com corda t, que cria esse pedaço de memória.
Praça passa a ser 32 bits na maioria dos computadores.
Na verdade, se você já ouviu falar de um computador com uma arquitetura de 32 bits,
muito chique-dizer, que apenas significa que ele usa endereços de 32 bits.
E como um técnico de lado, Se você já se perguntou
Por que os computadores mais antigos, se você realmente tentou sopa-los com muita memória RAM,
apenas pode ter um máximo de quatro gigabytes de RAM,
bem isso é porque, literalmente, computador antigo só podia
Quantidade de tão elevada como 4 bilhões, 4 bilhões de bytes,
porque se utilizando 32 bits números de endereços.
>> Mas em qualquer caso, neste exemplo, da história muito mais simples.
t é apenas um outro ponteiro, ou realmente uma estrela char, aka string.
E como eu gostaria de atualizar esta imagem agora com essa segunda linha de código,
após o ponto, ponto, ponto?
Quando eu faço corda t é igual a s ponto e vírgula, como é que esta imagem mudar?
Sim?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Yeah.
Exatamente.
Acabei de colocar uma flecha t caixa para o mesmo endereço,
a mesma primeira letra deu.
Ou tecnicamente, se esta cara ainda estava em 0x1,
é como se eu tivesse Aqui 0x1 e 0x1 aqui.
Mas, novamente, quem se importa sobre os endereços?
É apenas a idéia de que agora importa.
Então é isso que está acontecendo aqui.
Então, é claro, se você fizer suporte t 0, que é a marcação de matriz,
de course-- e, francamente, parece como se houvesse uma matriz por aqui,
mas agora há uma coisa estranha.
Saiba que a linguagem de programação, C, oferece esse recurso,
pelo que, mesmo que t é um ponteiro, ou s é um ponteiro,
você ainda pode usar aquele familiar, colchete confortável
notação para ir para o primeiro elemento, ou o segundo elemento, ou qualquer elemento
que esse ponteiro está apontando para porque, presumivelmente, ele
é, como no caso presente, apontando para alguma matriz.
>> Então, como vamos resolver isso?
Francamente, isso é onde ele tem um pouco esmagadora à primeira vista.
Mas aqui é uma versão nova e melhorada.
>> Então, primeiro, eu estou ficando livrar da biblioteca CS50,
apenas para expor que s é de facto uma estrela char, apenas um sinônimo.
E t é também uma estrela de char.
Mas o que está acontecendo no do lado direito da linha
onde t é atribuído um valor?
>> O que é malloc?
O que é strlen?
O que é sizeof (char)?
Por que diabos faz isso olhar linha tão complexo?
O que está fazendo em um nível elevado?
O que é que o armazenamento em t?
Sim?
AUDIÊNCIA: É a atribuição de uma certa quantidade de espaço de memória.
É para guardar, eu acho, letras [inaudível].
>> DAVID J. MALAN: Perfeito.
Perfeito.
É atribuição de um certo quantidade de espaço de memória
para armazenar, presumivelmente, cartas futuras.
E, em particular, malloc portanto, está retornando de uma coisa?
>> AUDIÊNCIA: Retornando o [inaudível]?
DAVID J. MALAN: Exatamente.
Retornando o endereço de que a memória, que é uma maneira elegante de dizer,
retorna o endereço do primeiro byte dessa memória.
A responsabilidade recai sobre mim para lembrar a quantidade de memória que eu realmente
alocado ou malloc pediu.
>> Agora quanto é isso?
Bem, mesmo que não haja um lote de parênteses aqui,
malloc leva apenas um único argumento.
E eu estou especificando strlen de s, para dar me como muitos bytes, como existem em s,
mas adicione um.
Por quê?
Sim?
>> AUDIÊNCIA: A barra invertida 0.
DAVID J. MALAN: Exatamente.
Temos que fazer um pouco de limpeza.
Então, porque não há uma barra invertida 0, é melhor se lembrar disso.
Caso contrário, nós vamos para criar uma cadeia que
não tem que terminador especial.
>> Enquanto isso, apenas para ser super anal, tenho sizeof (char),
apenas no caso de alguém corre o meu código não no aparelho CS50,
mas talvez um computador diferente ao todo, onde chars
é um byte, por convenção, mas dois bytes, ou algo maior do que isso.
É apenas para ser super, Super aversão a erros.
Mesmo que, na realidade, é provavelmente vai ser um 1.
>> Agora, enquanto isso, eu vou em frente e copiar o corda, suporte t i é igual a faixa t s.
E eu vou adiar para a última semana código-fonte para ver o que está acontecendo.
Mas o principal argumento, eo razão de eu colocar o código agora em verde,
é porque essa última linha, t suporte 0 é igual a toupper,
tem o efeito de capitalizar que seqüência?
t e / ou s?
Essa última linha de código.
>> Apenas t, porque o que é aconteceu desta vez,
se eu ligeiramente desfazer o último passo, O que aconteceu é, quando eu chamo malloc,
Eu essencialmente obter um pedaço de memória que é do mesmo tamanho que o inicial,
porque essa é a aritmética que eu fiz.
Eu estou armazenando em t endereço desse pedaço de memória.
Mesmo que isso parece bom e bonito, agradável e em branco,
A realidade é que é, o que vamos continuam chamando, os valores de lixo aqui.
Esse pedaço de memória pode muito muito bem ter sido usado antes,
alguns segundos, alguns minutos atrás.
Portanto, não poderia absolutamente ser números ou letras lá, apenas por acaso.
Mas eles não são válidos, até que eu me preencher este pedaço de memória
com caracteres reais, como eu fazer nesse loop for lá.
Tudo certo?
>> Então, agora, o clímax da Estes três exemplos
que foram aparentemente quebrado última vez, Neste exemplo swap, esta função
trabalhou no sentido que trocou a e b.
Mas não deu certo em que outro sentido?
Sim?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Exatamente.
Se eu fosse para chamar esta função de another-- por exemplo,
a partir de uma função como principal, onde Eu tenho uma variável, x e y, como eu
fez na semana passada, o mesmo código, e eu passar em x e y
Trocar e depois chamar Swap-- isso, é claro, é a versão correta
é o que estamos prestes a ver-- não funcionou.
Então, qual é a correção?
>> Bem, então, basta ser claro, deixe-me ir em frente
e-- me dar um segundo aqui, e ver se eu posso mostrar-lhe a última, que
será em-- vamos ver se eu posso encontrar esta OK fast-- real, [inaudível].
OK, ele está lá.
Assim, ignorar os comandos que eu estou apenas digitando.
Eu quero que ele recuperar a o último minuto de um exemplo
desde a última vez, que agora é chamado de não trocar.
>> Portanto, não Swap é onde paramos da última vez,
pelo qual, I inicializada x e y de um para dois.
Eu, então, chamar de Swap, passando em 1 e 2.
E então esta função trabalhou em algum sentido,
mas não tinha permanente efeito de x e y.
Então, a questão em apreço é, como agora é que vamos realmente resolver este problema?
Qual é a solução na mão?
>> Bem, em swap.c, que é novo hoje, notar algumas diferenças.
x e y são o mesmo.
Mas o que é claramente diferente sobre linha 25?
O que há de novo lá, se você se lembra o que parecia um segundo atrás?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Yeah.
Assim, os ampersands são uma nova peça de sintaxe, não só neste programa,
mas também em termos mais gerais em CS50.
Até o momento, eu não acho que temos conhecimento de exemplos
ou realmente falado sobre eles em qualquer detalhe, exceto, talvez, preventivamente
em corte, um e comercial como este.
Bem, acontece que é um comercial dos últimos pedaços de nova sintaxe
vamos aprender.
Tudo isto significa é o endereço de alguma variável.
Em que endereço se x viver?
Mas o endereço que y viver?
Porque se o problema fundamental antes
foi que x e y eram transferidos como cópias, o que nós realmente queremos fazer
é fornecer Swap com como um tesouro mapa que leva a que x e y efectivamente
estão na RAM, para que Trocar pode seguir esse mapa
e ir para onde quer que x ou y marca o local e alterar os valores reais 1 e 2
lá.
>> Então trocar precisa mudar um pouco também.
E, à primeira vista, isso pode parece um pouco semelhante ao carvão estrela.
E de fato é.
Assim, um é um ponteiro para o tipo de dados, com base nesta porção destacada?
Portanto, é um int.
>> Assim, um não é mais um int, é o endereço de um int.
E da mesma forma, b agora vai para ser o endereço de um int.
Então, quando eu agora chamo de swap de Main, Eu não vou dar Trocar 1 e 2.
Vou dar-lhe como Ox-algo e Ox-alguma coisa,
dois endereços que levarão Trocar para seus locais reais
na memória do meu computador.
>> Então, agora, minha implementação restante precisa mudar um pouco.
O que é, obviamente, diferente agora nestas três linhas de código?
Há essas estrelas malditos todos sobre o lugar, certo?
Então, o que está acontecendo aqui?
Sim?
>> AUDIÊNCIA: É, obviamente, [inaudível].
>> DAVID J. MALAN: Exatamente.
Portanto, neste context-- e isso não era a melhor decisão de projeto, na verdade,
anos atrás.
Neste contexto, em que você só tem uma estrela,
e você não tem um tipo de dados, como int, imediatamente à esquerda,
em vez disso você tem um sinal de igual, de forma clara, Neste contexto, quando você diz que estrelar um,
isso significa ir para a endereço que está em um.
Siga o mapa do tesouro, por assim dizer.
>> E enquanto isso, na linha 37, isso significa a mesma coisa.
Vá para o endereço de um, e colocar o que há?
Seja qual for a local que b especifica.
Em outras palavras, ir para b.
Obter esse valor.
Vá a uma e, por igual assinar, o operador de atribuição,
colocar esse valor lá.
>> Da mesma forma, int temperatura é apenas um int.
Nada precisa mudar em Temp.
É apenas um copo de reposição de Annenberg um pouco de leite ou suco de laranja.
Mas eu preciso dizer, ir para b.
Vá para esse destino e colocar o valor em temperatura lá.
Então, o que está acontecendo, então?
Quando eu realmente chamar Troque esse tempo, se esta primeira bandeja aqui representa principal,
Nesta segunda bandeja representa swap, quando Eu passo Ampersand x e y comercial
de principal de trocar, só para ficar claro, o que é esse quadro de pilha de recepção?
Sim?
>> AUDIÊNCIA: [inaudível].
DAVID J. MALAN: Exatamente.
O endereço de x e o endereço de Y.
E você pode pensar neles como endereços postais.
33 Oxford Street e 35 Oxford Street, e você
deseja mover os dois edifícios que estão nessas localizações.
>> É uma espécie de uma idéia ridícula, mas isso é tudo que queremos dizer por endereço.
Onde no mundo pode você encontra esses dois inteiros?
Onde no mundo você pode encontrar os dois edifícios?
Então, se finalmente, depois de todo esse tempo eu entrar em código-fonte e compilar de hoje
Trocar e correr ./swap, finalmente, para o primeira vez que nós realmente vemos que
meus valores têm, na verdade foi trocado com sucesso.
E agora, podemos até ter conhecimento do presente, digamos, gdb.
>> Então deixe-me ir para o mesmo arquivo.
Deixe-me ir em frente e correr gdb de ./swap.
E agora, em trocar, eu estou indo para ir em frente e definir um ponto de ruptura na principal.
E agora eu estou indo para ir em frente e executar o programa.
E agora vamos ver o meu código parou na linha.
>> Se eu ir em frente e impressão x, o que devo ver aqui?
É uma pergunta.
Diga de novo?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Então números aleatórios, talvez.
Talvez eu tenha sorte, e é agradável e simples, como 0.
Mas talvez seja algum número aleatório.
Neste caso, eu tive sorte.
Ele só passa a ser 0.
Mas é realmente sorte, porque não até que eu
tipo seguinte e, em seguida, imprimir x tem que linha de código, linha 19, foram executados.
>> Enquanto isso, se eu digitar próxima vez, e agora imprimir y, eu vou ver 2.
Agora, se eu digitar em seguida, ele vai ficar um pouco confuso, porque agora,
o printf vai aparecer a tela, como o fez. x é 1.
>> Vamos fazer isso de novo.
E agora, aqui é onde as coisas começam a ficar interessantes.
Antes de me chamar de Swap ou mesmo passo para ele, vamos dar uma olhadinha.
x é, de novo, 1.
Y é, é claro, sanidade rápido verificar, 2, por isso não é difícil lá.
Mas o que é comercial x?
Resposta, é uma espécie de vista funky.
Mas a estrela int em parênteses é apenas maneira de PIB de dizer isto é um endereço.
Não é um int, que é um ponteiro para um int, ou de outro modo conhecido como um endereço.
>> O que é essa coisa louca?
Nunca vimos algo bem assim antes.
Portanto, este é o endereço no meu computador de memória de onde x acontece a viver.
É Ox-alguma coisa.
E este é, francamente, por que Eu comecei a desenhar setas,
em vez de números, porque quem realmente se importa
que é o seu int num determinado endereço que é assim tão grande.
Mas bffff0c4, todos estes são na verdade dígitos hexadecimais,
que vão de 0 a f.
>> Então, nós não vamos morar muito tempo em que essas coisas são.
Mas se eu imprimir y, é claro, eu vejo 2.
Mas comercial y, vejo este endereço.
E aviso, para os curiosos, Qual a distância entre x e y?
Você pode ignorar a maior parte do endereço.
Quatro bytes.
E isso é consistente com nossa anteriormente afirmam que o tamanho é um int?
Quatro bytes.
Portanto, parece que tudo está se alinhando bem, como você poderia esperar, na memória.
>> Então, agora, vamos avançar rapidamente para o final desta história.
Vamos em frente e digite passo, para mergulhar na Função Swap.
Agora note, se eu digitar um, é idêntico ao endereço de x.
Se eu digitar b, é idêntica para o endereço de y.
Então, o que eu deveria ver se eu dizer, ir para o endereço de um?
Assim imprimir estrelar um.
Assim estrela significa ir lá, neste contexto.
Ampersand significa que é o endereço.
Assim, uma forma estrelar 1.
E estrela de impressão b me dá 2.
>> E deixe-me assumir, para o momento, que pelo menos o código que
continuará a executar pode ser agora fundamentado por meio dessa forma.
Mas vamos voltar a esta idéia em pouco tempo.
Portanto, esta versão do swap é agora correcta e permite
nos para trocar este tipo de dados particular.
>> Assim, todas as perguntas, então em Trocar?
Em estrela?
No endereço?
E você vai ver, com conjunto de problemas 4, de alguma forma,
mas o problema ajuste 5, definitivamente, a forma como estes as coisas são úteis e obter muito mais
confortável com eles, como um resultado.
Qualquer coisa?
Tudo certo.
Então malloc é, novamente, esta função que apenas aloca memória, a memória
alocação.
E por que isso é útil?
Bem, todo esse tempo, você estiver usando malloc.
Se você considerar agora como GetString obras, presumivelmente, é
foi pedir a alguém por um pedaço de memória, a qualquer momento o usuário digita uma string
no, porque certamente não sabia, como pessoal CS50,
como aquelas cordas grande que os seres humanos estão indo para escrever poderia ser.
>> Então, vamos, pela primeira vez, começar a Descasque todas como funciona a biblioteca CS50,
por meio de um par de exemplos que nos levará lá.
Então, se eu abrir gedit e abrir scanf 0,
vamos ver o seguinte código.
Scanf 0, disponível no site para hoje, tem relativamente poucas linhas de código
aqui, 14 a 20.
E vamos ver o que ele está fazendo.
Ele declara um int, chamado x.
Ele diz algo como, número por favor.
E agora ele diz, scanf% i, e x.
Portanto, há um monte de coisas novas lá.
>> Mas scanf, você pode tipo de pensar como o oposto de printf.
printf, é claro, para a impressão em tela.
tipo scanf de scans do usuário do teclado algo que ele ou ela tenha digitado.
>> % I é como printf.
Isto significa que a espera usuário digite um int.
E agora, por que você acha que eu pode estar passando scanf & x?
Se o objetivo de vida de scanf é fazer com que algo do usuário,
qual é o significado de passando-o, & x, agora?
Sim?
>> AUDIÊNCIA: [inaudível].
DAVID J. MALAN: Exatamente.
Tudo o que eu, o ser humano, datilografar, minha entrada vai ser salvo no local.
Não é suficiente, lembre-se, apenas passar em x, porque a gente já viu,
qualquer momento que você passa apenas uma variável cru, como um inteiro, de alguma outra função,
Claro, isso pode mudar isso variável, mas não permanentemente.
Não pode ter um efeito sobre Principal.
Ela só pode mudar sua própria cópia local.
Mas se, em vez disso, você não dá-me a real int,
mas você me dar instruções para int que, agora, sendo scanf,
Certamente, eu posso seguir esse abordar e colocar um número não
para que você tenha acesso a ele também.
>> Então, quando eu executar este programa, vamos ver.
Faça scanf 0 ponto barra, scanf 0.
E se eu agora digite um número como 50, graças ao 50.
Se eu agora digite um número como 1 negativo, para o negativo 1.
Agora digite um número como 1,5, hm.
Por que meu programa me ignorar?
Bem, porque simplesmente, eu te disse que esperar só um int.
Tudo certo.
Então essa é uma versão deste.
Vamos levar as coisas acima de um entalhe e propor que isso não é bom.
E aqui reside um exemplo muito simples de como podemos começar a escrever código
que outras pessoas possam explorar ou comprometer, fazendo coisas ruins.
Assim, linha 16, tão semelhantes em espírito de antes,
mas eu não estou declarando-o int neste momento.
Eu estou declarando-o caractere estrela, também conhecido como corda.
>> Mas o que isso realmente significa?
Então, se eu não especificar uma address-- e Eu estou chamando-o de forma arbitrária, buffer,
mas eu poderia chamá-lo é, para ser simple-- e então eu faço isso, me explique,
se você pudesse, com base na anterior lógica, o que está fazendo no scanf linha 18,
se passe% s e buffer, qual é o endereço?
O que é scanf, se você aplicar o exatamente a mesma lógica que a versão 0,
vou tentar fazer aqui, quando o usuário digita algo em?
Sim?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Exatamente.
Scanf, pela lógica anterior, vai levar a string
que o digitado humano em-- agora é uma string,
não é um número, presumivelmente, se ele ou ela cooperates--
e vai tentar colocar isso seqüência na memória em qualquer endereço
tampão especifica.
E isso é ótimo, porque o buffer é realmente concebido para ser um endereço.
>> Mas eu reivindico este programa é buggy em um forma muito grave, porque o valor é
tampão por padrão?
O que eu inicializado em?
O pedaço de memória?
Eu não tenho, certo?
>> Então, mesmo que eu tenha atribuído um estrela de char que já não se chama s,
é chamado em vez, de modo buffer-- vamos desenhar o nome da variável
agora como buffer-- se eu não tenho chamado getString ou malloc aqui,
que efetivamente significa que tampão é apenas um valor de lixo.
>> Agora, o que isso significa?
Isso significa que eu tenho dito scanf esperar uma string do usuário.
E você sabe o quê?
O que quer que essa coisa está apontando para-- e eu chamar ponto de interrogação,
mas, na realidade, ele vai ser algo como OX 1, 2, 3, certo?
É um valor falso que apenas passa a ser lá de antes.
Então, dito de outra forma, é como se tampão é apenas
apontando para algo na memória.
Eu não tenho nenhuma idéia do que.
>> Então, se eu digitar gabe agora, vai para tentar colocar g-a-b-e / 0 não.
Mas quem sabe o que é isso?
E, no passado, qualquer vez que tentei tocar
memória que não pertence para nós, o que aconteceu?
Ou quase sempre.
Falha de segmentação, certo?
>> Esta seta, eu não tenho nenhuma idéia de onde ele é apontador. É só um valor aleatório.
E, claro, se você interpretar um valor aleatório como endereço,
você está indo para ir para algum destino aleatória.
Então gabe pode de fato acidente meu programa, neste caso aqui.
>> Então o que podemos fazer isso é quase tão ruim?
Considere este terceiro e último exemplo de scanf.
Esta versão é melhor em que sentido?
Se você está confortável com o problema anterior, este é melhor.
Por quê?
>> AUDIÊNCIA: [inaudível].
DAVID J. MALAN: Good.
Então, neste caso, da linha 16 é melhor, no sentido
que estamos explicitamente a atribuição de uma memória.
Nós não estamos usando malloc, estamos usando a 2 semanas
abordagem de apenas declarar uma matriz.
E nós dissemos antes que uma seqüência é apenas um conjunto de caracteres,
então isso é totalmente legítimo.
Mas é, naturalmente, como você nota, tamanho fixo, 16.
>> Portanto, este programa é totalmente seguro, se eu digitar
em seqüências de um personagem, de dois caracteres cordas, 15 cadeias de caracteres.
Mas assim que eu começar a digitar 16, 17, 18, 1000 cadeias de caracteres,
onde está essa corda vai acabar?
Vai acabar em parte aqui.
Mas, então, quem sabe o que mais está além dos limites
desta variedade particular?
>> É como se eu tivesse declarou 16 caixas aqui.
Então ao invés de tirar todos os 16, vamos fingir que eu desenhei 16.
Mas se eu tente ler uma string que é muito mais longo, como 50 caracteres,
Eu vou começar a colocar a, b, c, d, x, y, z.
E esta é presumivelmente algum outro segmento de memória
que, de novo, pode causar meu programa trave,
porque não pediu nada mais do que apenas 16 bytes.
>> Então, quem se importa?
Bem, aqui está a biblioteca CS50.
E a maior parte deste é apenas como instruções em cima.
A biblioteca CS50, todo esse tempo, teve esta linha na linha 52.
Vimos typedef, ou você vai ver typedef
em pset 4, que apenas cria uma sinônimo pelo qual caractere estrela pode ser mais
simplesmente referido como string.
Portanto, este é um dos algumas rodinhas
nós usamos secretamente debaixo do capô.
>> Enquanto isso, aqui está a função, getchar.
Agora, aparentemente, não há corpo para ele.
E, de fato, se eu continuar rolagem, eu realmente não
ver qualquer implementações destas funções.
Como uma verificação de sanidade, por que isso?
>> AUDIÊNCIA: [inaudível].
DAVID J. MALAN: Yeah.
Portanto, este é o arquivo de cabeçalho.
E arquivos de cabeçalho contêm protótipos, além de algumas outras coisas, ao que parece,
como typedefs.
Mas em CS50.c, que nós temos nunca lhe dado a título definitivo,
mas foi no aparelho CS50 todos desta vez, bem no fundo de suas pastas,
notar que não há um todo monte de funções aqui.
>> Na verdade, vamos rolar para baixo.
Vamos ignorar a maioria deles, por enquanto.
Mas desça até getInt e ver como getInt funciona.
Então aqui está getInt.
E se você realmente se importa como chegar int funciona, aqui é a sua documentação.
E entre as coisas ele diz é que lhe diz
que as gamas de valores que pode retornar.
É essencialmente negativo 2000000000 para o positivo 2 bilhões, mais ou menos.
>> E ao que parece, tudo isso tempo, mesmo que nunca
tinha que verificar para ele, Se algo der errado,
verifica-se que todos os Neste momento, tem getInt
foram retornando um especial constante, não nulo,
mas sim INT_MAX, que é convenção apenas um programador.
Isso significa que aqui é um valor especial.
Certifique-se de verificar isso, basta no caso de algo correr mal.
Mas nunca se preocupou com que até à data,
porque mais uma vez, este destina-se a simplificar.
>> Mas como é que se getInt implementado?
Bem, um, ele não tem argumentos.
Nós sabemos disso.
Ele retorna um int.
Nós sabemos disso.
Então, como é que funciona debaixo do capô?
>> Portanto, não há, aparentemente, um infinito ciclo, pelo menos o aparecimento de um.
Observe que estamos usando getString.
Então, isso é interessante. getInt chama a própria função, getString.
E agora por que isso poderia ser o caso?
Por que estou sendo defensiva aqui na linha 165?
O que poderia acontecer em linha 164, só para ficar claro?
É a mesma resposta de antes.
Pode ser apenas falta de memória.
Algo vai mal com getString, temos de ser capazes de lidar com isso.
E a razão de eu não retornam nulo é que, tecnicamente, null é um ponteiro.
getInt tem que retornar um int.
Então, eu tenho arbitrariamente decidiu, essencialmente,
que 2 bilhões, mais ou menos, vai ser um valor especial que eu nunca pode
realmente obter do usuário.
É apenas o valor que eu vou para o lixo para representar um código de erro.
>> Então, agora, as coisas ficam um pouco de fantasia.
E não é bem a mesma função como antes, mas é muito similar.
Então, observe, eu declaro aqui, na linha 172, tanto um int n e um char c.
E então eu uso essa linha funky, sscanf, o que se vê
não verifica uma string a partir do teclado.
Ergue-se uma seqüência existente que o usuário já digitou.
Então, eu já chamado getString, que significa que eu tenho uma string na memória.
sscanf é o que você chamar uma função de análise.
Ele olha para a cadeia eu tenho digitada, caractere por caractere,
e faz alguma coisa útil.
Essa seqüência é armazenado na fila.
E eu sei que só indo voltar aqui e dizer, oh, OK,
Liguei para ele não s neste momento, mas a linha.
>> E agora isso é um pouco diferente.
Mas isso significa que de forma eficaz, por razões que de certa forma vai acenar as mãos no hoje,
que estamos verificando a ver se o usuário digitou
e int e talvez um outro personagem.
Se o usuário digitou em um int, é vai ser armazenados em n, pois estou
passando por este endereço, o novo truque que vimos hoje.
Se o usuário também digitado em como 123x, que x
vai acabar um carta em caráter c.
>> Agora verifica-se que sscanf vai me dizer, de forma inteligente,
quantas variáveis ​​foi sscanf com sucesso capaz de preencher.
Então, por esta lógica, se a função Estou implementando é getInt,
mas estou verificando, , potencialmente, para o utilizador
ter digitado em um int seguido por outra coisa,
o que eu quero de sscanf valor de retorno realmente ser?
Se o objectivo é obter apenas um int do usuário?
>> Então, se sscanf retornos 2, o que significa isso?
O usuário digitou algo como, literalmente,
123x, o que é absurdo.
É uma condição de erro, e Quero verificar para isso.
>> Portanto, se o usuário digita isso em, pelo Nessa lógica, o que faz sscanf voltar,
que você diria?
Então, ele vai retornar 2, porque o 123 vai entrar aqui,
eo x vai acabar aqui.
Mas eu não quero que o x para ficar cheio.
Quero sscanf apenas ter sucesso em encher a primeira das suas variáveis.
E é por isso que eu quer sscanf para retornar 1.
>> E se isto é um pouco sobre a cabeça para o momento, isso é totalmente bom.
Perceba, porém, que um dos valores de getInt e getString
é que estamos fazendo um pedaço de um monte de verificação de erros como este para
que, até agora, você pode muito bem digitar nada no teclado,
e nós vamos pegá-lo.
E certamente, o pessoal, não é definitivamente
ser a fonte de um bug em seu programa, porque estamos na defensiva
verificação de todos os estúpidos coisas que um usuário pode fazer,
como digitar um texto, quando você realmente queria int.
Assim, para agora-- nós viremos de volta a este antes long--
mas todo esse tempo, getString e getInt ter
sido por baixo do capuz com esta ideia básica de endereços de memória.
>> Então, agora, vamos tornar as coisas um pouco mais user-friendly.
Como você pode recordar, a partir de Binky última tempo-- se meu mouse vai cooperate-- assim
tivemos esse código, que francamente, é bastante absurda.
Este código obtém nada útil, mas foi o exemplo
que o professor Parlante utilizado para representar
o que estava acontecendo em um programa envolvendo memória.
>> Então, vamos recontar essa história de super brevemente.
Estas duas primeiras linhas, em Inglês, fazer o quê, você diria?
Apenas no razoavelmente humano, mas ligeiramente termos técnicos, tomar uma facada.
AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: OK, você está estabelecendo endereços para o seu variáveis ​​x e y.
Não é bem assim, pois x e y não são variáveis ​​no sentido tradicional.
x e y são endereços ou vai armazenar o endereço.
Então, vamos tentar mais uma vez.
Não é um mau começo, no entanto.
Sim?
>> AUDIÊNCIA: [inaudível].
DAVID J. MALAN: Good.
Eu acho que é um pouco mais limpo.
Declarando dois ponteiros, dois inteiros.
E nós estamos chamando-x e y.
Ou, se fosse desenhar isto como uma imagem de, novamente,
lembro muito simplesmente que todos estamos fazendo com que a primeira linha
está desenhando uma caixa como esta, com algum valor de lixo na mesma,
e chamando-x, e depois outra caixa como esta,
com um valor de lixo nele, chamando-y.
Nós já declarou dois ponteiros que, em última instância
irá armazenar o endereço de um int.
Então, isso é tudo que existe.
>> Então, quando Binky fez isso, o argila apenas olhou como este.
E Nick apenas um tipo de embrulhado as setas,
como se eles não estão apontando para qualquer lugar em particular, porque eles são apenas
valores de lixo.
Eles não estão explicitamente inicializado em qualquer em particular.
>> Agora, a próxima linha de código, recall, era isso.
Assim, em razoavelmente user-friendly, mas o Inglês um pouco técnico,
o que é essa linha de código está fazendo?
Sim?
>> AUDIÊNCIA: [inaudível].
>> DAVID J. MALAN: Perfeito.
É atribuição da parcela do memória que é do tamanho de um int.
E isso é metade da resposta.
Você respondeu à direita metade da expressão.
O que está acontecendo na lado esquerdo do sinal de igual?
Sim?
AUDIÊNCIA: e atribui à variável x?
>> DAVID J. MALAN: e atribui à variável x.
Então, para recapitular, aloca lado direito memória suficiente para armazenar um int.
Mas malloc especificamente retorna o endereço
desse pedaço de memória, o que você tem apenas proposto fica armazenado em x.
>> Então, o que Nick fez da última vez com Binky é ele arrastou esse ponteiro para fora, o barro,
para apontar agora em um pedaço branco de memória que é igual ao tamanho de um int.
E, de fato, que significou para representar quatro bytes.
>> Agora, a próxima linha de código fez isso, estrela x recebe 42.
Então 42 é simples na lado direito, sentido da vida.
Lado esquerdo, estrela x significa o quê?
Isso também pode ter gone-- está tudo OK.
Está bem.
>> AUDIÊNCIA: Basicamente, ir para o [inaudível]
DAVID J. MALAN: Good.
AUDIÊNCIA: [inaudível].
DAVID J. MALAN: Exatamente.
Lado esquerdo significa ir para x.
x é o endereço.
É como 33 Oxford Street, ou OX 1.
E estrela x significa ir àquela tratar e colocar o que há?
42.
>> Então, na verdade, isso é exatamente o que Nick fez.
Ele começou com pelo, essencialmente, mentalmente
apontando o dedo para x, seguindo a seta
para a caixa branca do lado direito lado, e colocar o número 42 lá.
Mas depois as coisas ficaram um pouco perigoso, certo?
Binky está prestes a perder a cabeça.
>> Estrela y é igual a 13, a má sorte, significa o quê?
Então meios y estrela ir para o endereço em y.
Mas qual é o endereço em y?
Tudo bem, é valor de lixo, certo?
Eu tirei-o como um ponto de interrogação.
Nick chamou-o como uma seta enrolado.
E assim que você tenta fazer estrela y, dizendo ir lá,
mas não há uma legítimo endereço, é uma localização falsa,
o programa vai falhar.
E a cabeça de Binky vai para voar aqui, como o fez.
>> Então, no final, este programa era apenas plana falha fora.
Era um programa de buggy.
E precisava ser corrigido.
E a única maneira, realmente, para corrigi-lo seria, por exemplo, esta linha de,
que nem sequer chegar, porque o programa caiu muito em breve.
Mas se tivéssemos de corrigir isso, o que efeito que fazer y iguais x tem?
Bem, essencialmente aponta y em qualquer valor x está apontando.
>> Assim, na história de Nick, ou a história de Binky, tanto
x e y foram apontando para o pedaço branco de memória,
de modo que, finalmente, quando não estrelar y é igual a 13, mais uma vez,
você acaba colocando 13 em o local apropriado.
Assim, todas estas linhas são perfeitamente legítima, com exceção de um presente,
quando isso aconteceu antes de você efectivamente atribuídos y algum valor.
>> Agora, felizmente, você não tem que raciocinar através de todos
desses tipos de problemas em seu próprio país.
Deixe-me ir em frente e abrir uma janela de terminal aqui
e abrir-se, por um momento, um super programa curto que
também é uma espécie de inútil.
É feio.
Não conseguir qualquer coisa útil.
Mas isso não demonstrar problemas de memória, por isso vamos dar uma olhada.
>> Principal, super simples.
Aparentemente, chama uma função, f, e, em seguida, retorna 0.
É meio difícil de estragar isso.
Então principal é muito bom, até agora.
>> Assim, f é problemático.
E só não colocar muito esforço em nomeá-lo
aqui, para manter o foco sobre o código.
f tem duas linhas.
E vamos ver o que está acontecendo agora.
Assim, por um lado aqui-- e deixe-me fazer
isto é consistente com a anterior example-- por um lado,
lado esquerdo está fazer o que, em Inglês?
Ele é--
AUDIÊNCIA: Criando um ponteiro.
DAVID J. MALAN: Criando um ponteiro para um int e chamando-x.
Então, é a criação de uma daquelas caixas Eu continuo desenhando na tela de toque.
E agora, na mão direita lado, malloc, é claro,
está alocando um bloco de memória.
E só para ficar claro, como quantidade de memória é, aparentemente,
alocação, se você acabou de tipo de fazer as contas aqui?
>> Portanto, é de 40 bytes.
E eu sei que só porque eu sei que um int, no aparelho CS50, pelo menos,
tem quatro bytes.
Assim, 10 vezes 4 é 40.
Então isso é armazenar um x, o endereço do primeiro de 40 ints que
Foram atribuídos espaço de volta, para trás, para trás, para trás.
>> E isso é o que é importante sobre malloc.
Não é preciso um pouco de memória aqui, um pouco aqui, um pouco aqui.
Dá-lhe um pedaço de memória, contiguamente, a partir da operação
sistema.
>> Agora, o que sobre isso, x suporte de 10 é igual a 0?
Linha arbitrária de código.
Não conseguir qualquer coisa útil.
Mas é interessante, porque x suporte 10--?
Sim?
>> AUDIÊNCIA: [inaudível]?
>> DAVID J. MALAN: x suporte 10 não tem de ser nulo.
O detalhe nulo só entra em jogo com cordas, na extremidade de uma corda.
Mas um bom pensamento.
>> Quão grande é essa matriz, mesmo embora eu tenha alocado 40 bytes?
É 0 a nove, certo?
É 10 ints, no total.
40 bytes, mas 10 ints, indexados de 0 a 0.
>> Então o que é que x suporte de 10?
Na verdade, é um pouco valor de lixo desconhecido.
É a memória que não pertence a mim.
Eu não deveria estar tocando que byte número 41, 42, 43, 44.
Eu estou um pouco longe demais.
>> E, de fato, se eu executar este programa, ele pode muito bem funcionar.
Mas, às vezes, tenhamos sorte.
E assim, apenas para demonstrar isso-- e, francamente,
você nunca sabe antes não ele-- vamos executar este.
Ele não chegou a falhar.
>> Mas se eu mudar isso, para exemplo, ser como 1.000,
para fazer isso realmente deliberada, vamos ver
se nós podemos fazê-lo falhar desta vez.
OK, ele não caiu.
Como cerca de 100.000?
Vamos refazê-lo, e agora executá-lo novamente.
Está bem.
Ufa.
Tudo certo.
Então, aparentemente, mais uma vez, estes segmentos de memória, por assim dizer,
são razoavelmente grande, para que possamos ter sorte novamente e novamente.
Mas no final, quando você chegar ridículo e realmente ir longe na tela,
você tocar memória que realmente, realmente não pertence a você.
>> Mas, francamente, estes tipos de erros estão indo
a ser cada vez mais difícil para descobrir por conta própria.
Mas, felizmente, como programadores, temos ferramentas que nos permitem fazer isso por nós.
Portanto, este é, talvez, um dos programas mais feios,
ainda mais feia do que a produção do gdb.
Mas sempre tem uma linha ou dois que são super úteis.
>> Valgrind é um programa que ajuda não depurar um programa, de per si,
mas encontrar relativas à memória problemas, especificamente.
Ele será executado automaticamente o código para você e procure pelo menos duas coisas.
Uma, que você fez algo acidental como a memória de toque
que não pertence a você?
Ele irá ajudá-lo a encontrar esses casos.
>> E dois, ele vai ajudar você encontrar algo chamado
vazamentos de memória, o que temos completamente ignorado, ingenuamente,
por algum tempo e felizmente.
Mas ao que parece, tudo Neste momento, quando
você chamou getString em muitos de nossos programas,
você está perguntando o funcionamento sistema para a memória,
mas você tem qualquer lembrança de cada vez dando-lhe
para trás, fazendo unalloc, ou livre, como é chamado.
Não, porque nunca pediu-lhe para fazê-lo.
>> Mas todo esse tempo, os programas você tem escrito em C
foram vazamento de memória, pedindo ao funcionamento
sistema para obter mais e mais memória para cordas e outros enfeites,
mas nunca entregá-la de volta.
E agora isso é um pouco de uma simplificação,
mas se você já executar o seu Mac ou seu PC por algum tempo, a abertura
muitos programas, talvez fechar programas,
e mesmo que o seu computador não caiu,
está ficando muito mais lento, como se fosse realmente
usando uma grande quantidade de memória ou recursos, apesar de,
se você não é mesmo tocar o teclado,
que pode ser-- mas não podia always-- ser que os programas que você está executando
tem-se vazamentos de memória.
E eles continuam pedindo o OS para mais e mais memória, mas esquecê-lo,
na verdade não usá-lo, mas portanto, levando a memória longe
de outros programas que possam querer isso.
Então, isso é uma explicação comum.
Agora aqui é onde Valgrind de saída é completamente
atroz aos menos e mais confortável iguais.
Mas o interessante material é bem aqui.
Ele está me dizendo uma gravação inválido de tamanho quatro acontece neste programa,
em particular, na linha 21 da memory.c.
>> Se eu ir para a linha 21, hm, há de fato é uma gravação inválido de tamanho quatro.
Por tamanho de quatro?
Bem, este number-- e poderia ser qualquer coisa é um int.
Então é quatro bytes.
Então, eu estou colocando quatro bytes onde eles não pertencem.
Isso é o que Valgrind está realmente me dizendo.
Além disso, também será me diga, como veremos,
como você executar isso em um pset futuro, se e quando você já vazou memória, o que de fato
Eu tenho, porque eu chamei malloc, mas eu realmente não tenho
chamado, neste caso, livre, que vamos finalmente ver
é o oposto de malloc.
>> Então, agora, eu acho, um exemplo final.
Então, este é um pouco mais arcano, mas é talvez
a maior razão para ter cuidado com a memória,
ea razão que muitos programas e / ou servidores web, até hoje,
são tomadas por bandidos em algum lugar na internet que estão de alguma forma
envio de pacotes falsos para o servidor tentando comprometer suas contas,
ou ter seus dados, ou apenas geralmente assumir uma máquina.
Buffer overflow, como o nome sugere, meios
transbordando não um int, mas um tampão.
E um buffer é apenas uma maneira elegante de dizer que é um monte de memória.
>> E, de fato, liguei para uma string antes de buffer, em vez de s.
Porque se é um buffer, como no sentido YouTube,
ou quando você está assistindo a um vídeo, você pode ter visto a palavra de tamponamento,
ponto, ponto, ponto.
É incrivelmente irritante.
E isso significa apenas que seu player de vídeo
está tentando baixar lotes de bytes, os lotes de bytes
a partir de um vídeo da internet.
Mas é lento, por isso ele está tentando baixar um monte deles
para encher um tampão, um recipiente, de modo que você tem suficiente bytes que ele pode, então,
mostrar-lhe o vídeo, sem parar constantemente.
Mas acontece, você pode têm uma memória intermédia para esta grande.
Mas tentar colocar essa quantidade de dados em isso, e muito as coisas ruins podem acontecer.
Assim, por exemplo, vamos olhar para este teaser final de um exemplo.
Este é outro programa que, à primeira vista,
não faz nada super útil.
Ele tem uma função principal que chama essa função, f.
E essa função, f, até aqui, tem uma matriz de char, chamado c, de tamanho 12.
E então ele está usando este nova função chamada strncpy.
>> Acontece que, com este simples, simples linha de código, apenas duas linhas,
temos feito todo o meu programa, e, portanto, todo o meu computador,
e minha conta de usuário, e meu disco conduzir potencialmente vulnerável a qualquer pessoa
quem sabe e é bom o suficiente para executar este programa com uma certa linha de comando
argumento.
Em outras palavras, se esse cara mau coloca dentro de argvargv [1], digitando
no teclado muito especialmente criado corda, não abc, 123, mas, essencialmente,
símbolos binários que representam executável código, um programa que ele ou ela escreveu:
com este programa simples, que é representativa de milhares de programas
que são igualmente vulneráveis, ouso dizer, ele ou ela pode vir a excluir todos
os arquivos no meu disco rígido, obter um alerta piscando para que ele ou ela pode
digitar comandos por conta própria, enviar e-mail todos os arquivos para mim.
Qualquer coisa que eu possa fazer, ele ou ela pode fazer com este código.
>> Não vamos resolver isso bastante ainda.
E, na verdade, ele vai envolver um pouco de imagem
como este, que nós vamos em breve para entender tudo melhor.
Mas por hoje, vamos terminar em o que é, felizmente, um pouco mais
compreensível piada XKCD, até retomar a próxima vez.
Tudo certo.
Vejo vocês na quarta-feira.
>> [MÚSICA DE JOGO]
>> Orador: E agora, no fundo pensamentos, por Daven Farnham.
A memória é como pular em uma pilha de folhas de ouro em uma tarde de domingo.
Vento soprando, lançando o seu hair-- oh, eu sinto falta dos dias when--
>> [Risos]