[Powered by Google Translate] [Semana 5] [David J. Malan - Harvard University] [Esta é CS50. - CS50.TV] Este é CS50 Semana, 5. Hoje e esta semana, apresentamos um pouco do mundo da ciência forense no contexto do Conjunto de Problemas 4. Hoje será uma palestra abreviada porque há um evento especial aqui depois. Então, vamos dar uma olhada e provocar estudantes e pais de hoje com algumas das coisas que são no horizonte. Entre eles, a partir de segunda-feira, você terá um pouco mais colegas. EDX, Harvard e MIT nova iniciativa online para OpenCourseWare e mais, está lançando no campus de Harvard, na segunda-feira, o que significa que na segunda-feira você terá, a partir de última contagem, 86 mil colegas adicionais que vai seguir juntamente com palestras CS50 e seções e orientações e conjuntos de problema. E, como parte disso, você vai se tornar membros da aula inaugural do CS50 e agora CS50x. Como parte deste momento, perceber que haverá algumas upsides também. Para se preparar para isso, para o grande número de estudantes, basta dizer que, embora tenhamos 108 TFs e CAs, não é bem a melhor relação professor-aluno, uma vez que atingiu 80.000 dos alunos. Nós não vamos ser problema para muitos classificação define manualmente, assim introduzido esta semana no conjunto de problemas será CS50 Check, que vai ser um utilitário de linha de comando dentro do aparelho que você vai ter uma vez que você atualizá-lo mais tarde neste fim de semana. Você vai ser capaz de executar um comando, check50, em seu próprio pset, e você vai ter um feedback instantâneo para saber se o seu programa é correta ou incorreta acordo com as especificações de design diferentes que nós fornecemos. Mais sobre isso na especificação do conjunto de problemas. Os colegas CS50x vai usar isso também. Set problema 4 é tudo sobre a ciência forense, e este pset estava realmente inspirado por algumas coisas na vida real pelo que, quando eu estava na faculdade eu internados por um tempo na Procuradoria do Condado de Middlesex District está fazendo o trabalho forense com o seu principal investigador forense. O que isso representou, como eu acho que eu mencionei algumas semanas passado, é a polícia do Estado de massa ou outros entrava, eles iriam deixar as coisas como discos rígidos, CDs e disquetes e similares, e, em seguida, o objetivo do escritório forense foi verificar se houve ou não era evidência de algum tipo. Esta foi a Unidade de Investigações Especiais, por isso era crime de colarinho branco. Era uma espécie mais preocupante de crimes, qualquer coisa que envolva algum tipo de mídia digital. Acontece que não que muitas pessoas escrevem um e-mail dizendo: "Eu fiz isso." Então, muitas vezes, essas pesquisas forenses não apareceu todos os frutos que muito, mas às vezes as pessoas escrevem e-mails desse tipo. Então, às vezes, os esforços foram recompensados. Mas, para levar até este pset forense, estaremos introduzindo no pset4 um pouco de gráficos. Você provavelmente levar estas coisas para concedido - JPEGs, GIFs e outros - estes dias. Mas se você realmente pensa sobre isso, uma imagem, assim como o rosto de Rob, pode ser modelada como uma sequência de pontos ou pixels. No caso da cara de Rob, existem todos os tipos de cores, e começamos a ver os pontos individuais, também conhecidos como pixels, uma vez que começou a fazer zoom in Mas se simplificar o mundo um pouco e dizer que isso aqui é Rob em preto e branco, para representar o preto e branco, podemos usar apenas binário. E se vamos usar binário, 1 ou 0, podemos expressar esta mesma imagem de rosto sorridente de Rob com esse padrão de bits. 11000011 representa o branco, branco, preto, preto, preto, preto, branco, branco. E por isso não é um grande salto em seguida, começar a falar sobre fotografias coloridas, coisas que você veria no Facebook ou levar com uma câmera digital. Mas, certamente, quando se trata de cores, você precisa mais bits. E bastante comum no mundo das fotografias é usar uma cor não-bit, como isso sugere, mas cor de 24 bits, onde você realmente obter milhões de cores. Assim como no caso quando o zoom no olho do Rob, que era um número qualquer de milhões de diferentes possibilidades coloridas. Então, nós vamos introduzir esta no Conjunto Problema 4, bem como no passo a passo, que será hoje às 3:30 em vez de 2:30 o habitual por causa de palestra de sexta-feira aqui. Mas o vídeo estará online amanhã como de costume. Também vamos apresentá-lo para outro formato de arquivo. Este é deliberadamente quis olhar intimidador no início, mas isso é apenas uma documentação alguma para uma struct C. Acontece que há anos a Microsoft ajudou a popularizar este formato chamado o formato de arquivo bitmap, bmp, e este foi um super simples, formato de arquivo gráfico colorido que foi usado por algum tempo e, por vezes ainda para papéis de parede em desktops. Se você acha que volta para o Windows XP e as colinas eo céu azul, que era tipicamente uma imagem BMP ou bitmap. Bitmaps são divertido para nós, porque eles têm um pouco mais de complexidade. Não é tão simples como esta grade de 0s e 1s. Em vez disso, você tem coisas como um cabeçalho no início de um arquivo. Portanto, em outras palavras, dentro de um arquivo bmp. É um monte de 0s e 1s, mas há algum adicional 0s e 1s lá. E acontece que o que nós provavelmente já um dado adquirido há anos - formatos de arquivo como. doc ou. xls ou. mp3, mp4., independentemente dos formatos de arquivo que você está familiarizado com - o que isso significa mesmo ser um formato de arquivo, porque no fim do dia, todos estes ficheiros usamos têm apenas 0 e 1. E talvez os 0s e 1s representam ABC através ASCII ou similar, mas no final do dia, ainda é apenas 0s e 1s. Assim, os seres humanos apenas ocasionalmente decidem inventar um novo formato de arquivo onde padronizar o que padrões de bits vai realmente significar. E, neste caso aqui, o pessoal que projetou o formato de arquivo bitmap disse que no primeiro byte em um arquivo bitmap, como denotado por 0 compensados ​​lá, lá vai ser algum enigmaticamente chamado bfType variável chamada, que só fica para o tipo de arquivo de bitmap, que tipo de arquivo bitmap é esta. Você pode inferir talvez da segunda linha que compensar 2, número de bytes 2, tem um padrão de 0s e 1s que representa o que? O tamanho de algo. E vai de lá. Então, no Conjunto Problema 4, você vai ser orientado por algumas destas coisas. Nós não vai acabar se preocupar com todos eles. Mas note que começa a ficar interessante em torno de byte 54: rgbtBlue, Verde e Vermelho. Se você já ouviu a sigla RGB - vermelho, verde, azul - esta é uma referência a esse pois verifica-se que você pode pintar todas as cores do arco-íris com uma combinação de vermelho e azul e verde. E, de fato, os pais no quarto pode recordar alguns dos primeiros projetores. Estes dias, você só vê uma luz brilhante que sai de uma lente, mas volta no dia em que teve a lente vermelha, lente azul, ea lente verde, e, juntos, destinado a uma tela e formou uma imagem colorida. E, muitas vezes, escolas de ensino médio e escolas secundárias teria aquelas lentes levemente torto, para que eram uma espécie de ver imagens duplas ou triplas. Mas essa era a idéia. Você tinha luz vermelha, verde e azul pintar um quadro. E esse mesmo princípio é usado em computadores. Assim, entre os desafios, em seguida, para você em Problema Set 4 vão ser algumas coisas. Um deles é para redimensionar uma imagem, para tomar um padrão de 0s e 1s, descobrir qual pedaços de 0s e 1s representam o que em uma estrutura como esta, e então descobrir como replicar os pixels - os vermelhos, os azuis, os verdes - dentro de modo que, quando uma imagem fica assim, inicialmente, pode parecer que esta vez depois disso. Entre os outros desafios que também vai ser que você vai ser entregue uma imagem forense de um arquivo real de uma câmera digital. E nessa câmera, era uma vez, foram um monte de fotos. O problema é que acidentalmente apagados ou teve a imagem corrompida de algum modo. Coisas ruins acontecem com câmeras digitais. E, assim, rapidamente copiado todo o off 0s e 1s de que o cartão para você, salva-los todos em um arquivo grande, e depois nós vamos entregá-los a você no Conjunto de Problemas 4 de modo que você pode escrever um programa em C com o qual se recuperar todas essas JPEGs, idealmente. E acontece que JPEGs, mesmo que sejam um pouco de um formato de arquivo complexo - eles são muito mais complexos do que este sorriso aqui - verifica-se que todos os JPEG inicia-se com os mesmos padrões de 0s e 1s. Então, usando, em última análise, um loop while ou um loop for ou similar, você pode iterar sobre todos os 0s e 1s nesta imagem forense, e cada vez que você ver o padrão especial que está definido na especificação conjunto de problemas, você pode assumir aqui é, com grande probabilidade, o início de um JPEG. E assim que você encontrar o mesmo padrão algum número de bytes ou kilobytes ou megabytes mais tarde, você pode assumir aqui é um JPEG segundo, a foto que eu tomei depois da primeira. Deixe-me parar de ler esse arquivo em primeiro lugar, começar a escrever este novo, ea saída do seu programa para pset4 vai ser cerca de 50 JPEGs. E se não é 50 JPEGs, você tem um pouco de um loop. Se você tem um número infinito de JPEGs, você tem um loop infinito. De modo que também será bastante caso comum. Então, isso é o que está no horizonte. 0 Quiz atrás de nós, perceber por meu e-mail que, invariavelmente, há pessoas que são ambos felizes, espécie de neutro, e triste ao redor questionário tempo 0. E por favor, chegar a mim, a cabeça TF Zamyla, sua própria TF, ou um dos CAs que você sabe, se você gostaria de discutir como as coisas correram. Então, para impressionar os pais aqui na sala, o que é a biblioteca CS50? [Risos] Bom trabalho. O que é a biblioteca CS50? Sim. >> [Aluno] É um conjunto pré-escrita de código [inaudível] Ok, bom. É um conjunto de pré-escrita de código que o pessoal escreveu, oferecemos a você, que oferece algumas funcionalidades comuns, coisas como me uma corda, me um int - todas as funções que estão listadas aqui. A partir de agora, começamos a realmente tomar essas rodinhas. Nós vamos começar a tirar uma série de você, que recordação era apenas um sinônimo para o tipo de dados real? >> [Vários alunos] Char *. * Char. Para os pais, que foi, provavelmente, [som faz whooshing]. Isso é bom. * Char vamos começar a ver na tela tudo o mais que podemos remover seqüência de nosso vocabulário, pelo menos quando se trata de realmente escrever código. Da mesma forma, nós vamos parar de usar algumas dessas funções tanto porque os nossos programas estão indo para obter mais sofisticado. Em vez de apenas escrever programas que ficam lá com um piscar prompt, à espera de que o usuário digite algo, você terá suas entradas a partir de outro lugar. Por exemplo, você vai levá-los a partir de uma série de bits no disco rígido local. Você vai em vez levá-los no futuro a partir de uma conexão de rede, algum site em algum lugar. Então, vamos descascar essa camada pela primeira vez e puxar para cima o Appliance CS50 e este arquivo chamado cs50.h, o que você tem # incluindo por semanas, mas vamos ver realmente o que está dentro do presente. O início do arquivo em azul é apenas um monte de comentários: informações sobre a garantia e licenciamento. Esta é uma espécie de paradigma comum em software porque um monte de software nos dias de hoje é o que é chamado de código aberto, o que significa que alguém tenha escrito o código e tornou disponível gratuitamente não apenas para correr e para usar, mas para realmente ler e alterar e integrar no seu próprio trabalho. Então é isso que você está usando, o software de fonte aberta, embora de uma forma muito pequena. Se eu rolar para baixo após os comentários, porém, vamos começar a ver algumas coisas mais familiares. Aviso no topo aqui que o arquivo cs50.h inclui um conjunto de arquivos de cabeçalho. A maioria destes, não vimos antes, mas um é familiar. Qual destes temos visto, ainda que brevemente, até agora? >> [Aluno] biblioteca padrão. Sim, biblioteca padrão. stdlib.h tem malloc. Uma vez que começamos a falar sobre alocação dinâmica de memória, que vamos voltar para a próxima semana, assim, começamos incluindo o arquivo. Acontece que bool e verdadeiro e falso na verdade, não existe em C, por si só a menos que você inclua esse arquivo aqui. Temos de semana foi incluindo stdbool.h de modo que você pode usar a noção de um. bool, verdadeiro ou falso Sem isso, você teria que classificar de fingir e usar um int e apenas arbitrariamente assumir que 0 é falso e 1 é verdadeira. Se rolar mais, aqui é a nossa definição de uma cadeia. Acontece que, como já disse antes, que esta estrela é onde realmente não importa. Você pode até ter todo o espaço ao redor. Nós neste semestre foram promovendo-o como esta para deixar claro que a estrela tem a ver com o tipo, mas percebe tão comum, se não um pouco mais comum, é colocá-lo lá, mas funcionalmente é a mesma coisa. Mas agora, se lermos mais para baixo, vamos dar uma olhada em GetInt porque usamos que, talvez, antes de mais nada neste semestre. Aqui está GetInt. Isto é o que? >> [Aluno] Um protótipo. >> Este é apenas um protótipo. Muitas vezes, temos que colocar protótipos no topo de nossa. Arquivos c, mas você também pode colocar protótipos em arquivos de cabeçalho, arquivos. h, como esta aqui de modo que quando você escreve algumas funções que você quer que outras pessoas para ser capaz de usar, que é exatamente o caso da biblioteca CS50, você não só implementar suas funções em algo como cs50.c, você também colocar os protótipos não no topo do arquivo, mas no topo de um arquivo de cabeçalho. Em seguida, o arquivo de cabeçalho é o que os amigos e colegas de incluir com # incluir no seu próprio código. Então todo esse tempo, você está incluindo todos os protótipos, efetivamente no topo do seu arquivo, mas por meio deste mecanismo # include, que essencialmente copia e cola este arquivo em seu próprio. Aqui está alguma documentação bastante detalhada. Nós praticamente um dado adquirido que GetInt recebe um int, mas acontece que há alguns casos de canto. E se o usuário digita um número que é muito grande, um quintilhões, que simplesmente não pode caber dentro de um int? Qual é o comportamento esperado? Idealmente, é previsível. Portanto, neste caso, se você realmente ler a cópia fina, você realmente verá que, se a linha não pode ser lido, INT_MAX este retorno. Nós nunca conversamos sobre isso, mas com base na sua capitalização, o que é provavelmente? [Aluno] A constante. >> É uma constante. É uma constante especial que é, provavelmente, declarou em um desses arquivos de cabeçalho que é até maior no arquivo, e INT_MAX é provavelmente algo como cerca de 2 bilhões, A idéia é que, porque precisamos de alguma forma significar que algo deu errado, temos, sim, tem 4 bilhões de números à nossa disposição: -2000000000 em até 2 bilhões, mais ou menos. Bem, o que é comum em programação é você roubar apenas um desses números, talvez 0, talvez 2 bilhões, talvez -2000000000, assim você gasta um de seus valores possíveis de modo que você pode cometer ao mundo que, se algo der errado, eu vou retornar esse valor super grande. Mas você não quer que o usuário digitar algo enigmático como 234 ..., um número muito grande. Você generalizá-lo em vez como uma constante. Então, realmente, se você estava sendo anal nas últimas semanas, a qualquer hora que você ligou GetInt, você deveria ter vindo a verificar com uma condição, se fez o tipo de usuário em INT_MAX, ou, mais especificamente, fez GetInt INT_MAX retorno, porque se o fizesse, que realmente significa que eles não digitá-lo. Algo deu errado neste caso. Portanto, este é o que é geralmente conhecido como um valor de sentinela, o que significa apenas especial. Vamos agora voltar para o arquivo c.. O arquivo C existiu no aparelho por algum tempo. E, de fato, o aparelho tem pré-compilados para você nessa coisa que chamamos de código objeto, mas ele simplesmente não importa para onde está porque o sistema sabe neste caso em que é: aparelho. Vamos rolar agora para getInt e ver como GetInt vem trabalhando todo esse tempo. Aqui temos comentários similares de antes. Deixe-me ampliar apenas o código porção. E o que temos para GetInt é o seguinte. Não é preciso de entrada. Ele retorna um int, enquanto (verdadeiro), por isso temos um loop infinito deliberada, mas provavelmente vamos sair dessa forma ou de voltar a partir desta. Vamos ver como isso funciona. Parece que estamos usando GetString nesta primeira linha dentro do loop, 166. Isto agora é uma boa prática, porque em que circunstâncias poderia voltar GetString a palavra-chave NULL especial? >> [Aluno] Se algo der errado. Se algo der errado. E o que poderia dar errado quando você chamar algo como GetString? Sim. >> [Aluno] Malloc falha em dar-lhe os ints. Sim. Talvez malloc falhar. Em algum lugar debaixo do capô, GetString está chamando malloc, que aloca memória, que permite que a loja de informática de todos os personagens que o utilizador escreve no teclado. E suponha que o usuário tinha um monte de tempo livre e mais digitado, por exemplo, de 2 bilhões de caracteres, mais personagens do que o computador ainda tem RAM. GetString tem de ser capaz de significar que para você. Mesmo que este é um super, super-canto caso incomum, ele tem de algum modo ser capaz de lidar com isto, e assim GetString, se voltou e ler sua documentação, faz em NULL retorno fato. Portanto, agora se GetString falhar, retornando NULL, GetInt vai falhar, retornando INT_MAX apenas como uma sentinela. Estes são apenas convenções humanas. A única maneira que você sabe que este é o caso é através da leitura da documentação. Vamos deslocar até onde o int é realmente chegado. Se eu rolar um pouco mais, na linha 170, temos um comentário acima destas linhas. Declaramos em 172 um int, n, e um char, c, e, em seguida, esta nova função, que alguns de vocês ter tropeçado antes, sscanf. Isso significa scanf string. Em outras palavras, dá-me uma corda e eu irá procurar por peças de informação de interesse. O que significa isso? Suponha que eu digitar, literalmente, 123 no teclado e pressione a tecla Enter. Qual é o tipo de dados de 123 quando retornou por GetString? >> [Aluno] String. É óbvio que é uma string, certo? Eu tenho um string. Então, é realmente 123, aspas fecha aspas, 123 com o 0 \ no final do mesmo. Isso não é um int. Isso não é um número. Parece um número, mas isso não é verdade. Então, o que GetInt tenho que fazer? Tem que analisar essa seqüência esquerda para a direita - 123 \ 0 - e de alguma forma converter para um inteiro real. Você poderia descobrir como fazer isso. Se você acha que volta para pset2, você provavelmente tem um pouco confortável com César ou Vigenère, assim você pode iterar sobre uma corda, você pode converter caracteres para ints. Mas que diabo, é um monte de trabalho. Por que não chamar uma função como sscanf que faz isso para você? Então sscanf espera um argumento - neste caso chamado de linha, que é uma cadeia. Você, então, especificar entre aspas, muito semelhante ao printf, o que você espera para ver nesta seqüência. E o que eu estou dizendo aqui é que eu espero ver um número decimal e talvez um personagem. E vamos ver por que este é o caso em apenas um momento. E acontece que esta notação é agora lembra de coisas que começaram a falar sobre pouco mais de uma semana atrás. O que é & n & c e fazendo por nós aqui? >> [Aluno] Endereço de n e endereço do c. Sim. Está me dando o endereço de n e endereço do c. Por que isso é importante? Você sabe que com funções em C, você sempre pode retornar um valor ou nenhum valor. Você pode retornar um int, uma corda, uma bóia, um char, qualquer que seja, ou você pode retornar vazio, mas você só pode retornar uma coisa ao máximo. Mas, aqui queremos sscanf para voltar me talvez um int, um número decimal, e também um. char, e eu vou explicar por que o char em um momento Você efetivamente quer sscanf para retornar duas coisas, mas isso não é possível em C. Você pode resolver isso passando em dois endereços porque assim que você entrega uma função de dois endereços, o que pode essa função fazer com eles? >> [Aluno] Escreva para esses endereços. Ele pode escrever para esses endereços. Você pode usar a operação de estrela e ir para lá, para cada um desses endereços. É uma espécie de este mecanismo de back-door, mas muito comum para alterar os valores das variáveis mais do que apenas um único local - neste caso, dois. Agora repare que eu estou verificando == 1 e depois retornando n se isso, de fato, avaliar a verdade. Então, o que está acontecendo? Tecnicamente, tudo o que realmente quer que aconteça em GetInt é esta. Queremos analisar, por assim dizer, queremos ler a seqüência - entre aspas-123 - e se parece que há um número lá, o que estamos dizendo sscanf fazer é colocar esse número - 123 - nesta variável n para mim. Então, por que então eu realmente tenho isso também? Qual é o papel de sscanf dizendo que você também pode obter um personagem aqui? [Resposta do aluno inaudível] >> Um ponto decimal realmente poderia funcionar. Vamos sustentar que pensou por um momento. O que mais? [Aluno] Poderia ser NULL. >> Bom pensamento. Poderia ser o caractere nulo. Não é verdade neste caso. Sim. >> [Aluno] ASCII. ASCII. Ou deixe-me generalizar ainda mais. O c% não é apenas para verificação de erro. Nós não queremos que haja um personagem após o número, mas o que isso me permite fazer é o seguinte. Acontece que sscanf, além de armazenar valores de n e c neste exemplo aqui, o que também não é ele retorna o número de variáveis ​​que colocar valores dentro Então, se você digitar apenas em 123, então apenas o% d vai corresponder, e só n fica armazenado com um valor como 123, e nada é colocado em c. C continua a ser um valor de lixo, por assim dizer - lixo, porque isso nunca foi inicializada com algum valor. Então, nesse caso, sscanf retorna 1 porque eu preenchido um dos ponteiros, caso em que grande, eu tenho um int para que eu liberar a linha para liberar a memória GetString que efectivamente atribuído, e então eu voltar n, mais se você já se perguntou onde que Repetir declaração vem, ele vem aqui. Assim, se, pelo contrário, eu digitar 123foo - apenas uma seqüência aleatória de algum texto - sscanf vai ver número, número, número, f, e vai colocar o 123 em n; vai colocar o f em c e depois voltar 2. Então nós temos, apenas usando a definição básica de comportamento sscanf, uma maneira muito simples - assim, complexo, à primeira vista, mas no final do dia mecanismo relativamente simples - de dizer que há um int e se assim for, é que a única coisa que eu encontrei? E o espaço em branco aqui é deliberada. Se você ler a documentação para sscanf, diz-lhe que, se você incluir um pedaço de espaço em branco , no início ou no final, sscanf também irá permitir que o utilizador, por qualquer razão, para bater 123 barra de espaço e que será legítimo. Você não vai gritar com o usuário só porque bateu a barra de espaço no início ou no final, que é apenas um pouco mais user-friendly. Quaisquer perguntas, então no GetInt? Sim. >> [Aluno] E se você só colocar em um char? Boa pergunta. E se você acabou de digitar em um char como f e pressione Enter sem nunca digitando 123? O que você acha que o comportamento desta linha de código seria então? [Resposta do aluno inaudível] Sim, então sscanf pode cobrir isso também porque, nesse caso, não vai encher n ou c. Vai em vez retornar 0, caso em que eu também estou pegando esse cenário porque o valor esperado que eu quero é 1. Eu só quero uma e apenas uma coisa a ser preenchido. Boa pergunta. Outros? Tudo bem. Não vamos passar por todas as funções aqui, mas o que parece ser, talvez, de participação remanescente é GetString pois verifica-se que GetFloat, GetInt, GetDouble, GetLongLong todos punt muito de sua funcionalidade para GetString. Então, vamos dar uma olhada em como ele é implementado aqui. Este parece um pouco complexo, mas usa os mesmos fundamentos que começamos a falar sobre a semana passada. Em GetString, que leva nenhum argumento conforme o vazio aqui e ele retorna um string, eu aparentemente estou declarando uma string chamada buffer. Eu realmente não sei o que vai ser usado para ainda, mas vamos ver. Parece que a capacidade é, por padrão 0. Não é bem certo onde isso vai dar, não sei o que n vai ser utilizado para, no entanto, mas agora está ficando um pouco mais interessante. Na linha 243, declaramos um int, c. Esta é uma espécie de um detalhe estúpido. Um char é de 8 bits, e 8 bits pode armazenar quantos valores diferentes? >> [Aluno] 256. >> 256. O problema é se você quer ter 256 diferentes caracteres ASCII, que há se você acha que volta - e isso não é algo para memorizar. Mas se você acha que volta para esse gráfico grande ASCII tivemos semanas atrás, foram, neste caso 128 ou 256 caracteres ASCII. Nós usamos todos os padrões de até 0s e 1s. Isso é um problema se você quiser ser capaz de detectar um erro porque se você já está usando 256 valores para seus personagens, você realmente não planejar com antecedência, porque agora você não tem nenhuma maneira de dizer, este não é um personagem legal, isto é alguma mensagem errada. Então, o que o mundo faz é que eles usam o maior valor próximo, algo como um int, para que você tenha um número louco de bits, 32, para 4 mil milhões de valores possíveis de modo que você pode simplesmente acabar usando, essencialmente, 257 deles, Um dos quais tem algum significado especial como um erro. Então vamos ver como isso funciona. Na linha 246, eu tenho essa grande loop while que está chamando fgetc, f arquivo significado, de modo getc, e depois stdin. Acontece que esta é apenas a maneira mais precisa de dizer ler a entrada do teclado. Teclado meio padrão de entrada, saída padrão significa tela, e erro padrão, o que veremos na pset4, significa que o ecrã mas uma parte especial da tela de modo que não é confundida com saída real que você pretende imprimir. Mas mais sobre isso no futuro. Então fgetc significa apenas ler um caracter do teclado e armazená-lo onde? Guarde-o em c. E em seguida, verificar - por isso estou usando apenas algumas conjunções booleanos aqui - verifique se não é igual - \ n, de modo que o usuário aperte Enter, nós queremos parar nesse ponto, fim do ciclo - e nós também queremos verificar a EOF constante especial, que se você saber ou adivinhar, o que isso significa? >> [Aluno] Fim do arquivo. Fim >> de arquivo. Este é o tipo de absurdo, porque se eu estou digitando no teclado, não há realmente nenhum arquivo envolvido nisso, mas isso é apenas uma espécie de o termo genérico utilizado para significar que nada mais é que vem dedos dos humanos. EOF - final do arquivo. Como um aparte, se você já atingiu Control D em seu teclado não, que você teria ainda - você bateu Controle C - Control D envia esta constante especial chamado EOF. Portanto, agora só temos alguns alocação dinâmica de memória. Assim, se (n + 1 Capacidade>). Agora eu vou explicar n. N é apenas quantos bytes estão atualmente no buffer, a seqüência que você está actualmente a construir-se a partir do usuário. Se você tem mais caracteres em seu buffer do que você tem capacidade de buffer, intuitivamente o que temos de fazer, então, é alocar mais capacidade. Então eu vou para pular um pouco da aritmética aqui e focar apenas esta função aqui. Sabe o que malloc é ou são, pelo menos geralmente familiar. Adivinha o que realloc faz. >> [Aluno] Adiciona memória. Não é bem a adição de memória. É realoca memória como segue. Se ainda há espaço no final da cadeia para dar-lhe mais do que a memória do que originalmente lhe dá, então você vai ter que memória adicional. Então você pode apenas continuar colocando personagens da corda de costas para trás, para trás. Mas se esse não é o caso, porque você esperou muito tempo e foi algo aleatório jogou na memória não mas não há memória extra aqui, tudo bem. Realloc vai fazer todo o trabalho pesado para você, mover a seqüência que você já leu em assim muito longe daqui, colocá-lo lá em baixo, e depois dar-lhe um pouco mais de pista naquele ponto. Assim, com um aceno de mão, deixe-me dizer que o que está fazendo GetString é que está começando com um buffer pequeno, talvez um caráter único, e se o usuário digita em dois personagens, GetString acaba chamando realloc e diz um personagem não foi o suficiente, dá-me dois personagens. Então, se você ler a lógica do circuito, que vai dizer o usuário digitou 3 caracteres, dá-me agora não dois, mas quatro personagens, então me dê 8, em seguida, dar-me 16 e 32. O fato de que eu estou dobrando a capacidade de cada vez significa que o buffer não vai crescer lentamente, ele vai crescer super rápido. E o que poderia ser a vantagem disso? Por que eu estou dobrando o tamanho do buffer mesmo que o usuário só precisa um personagem extra a partir do teclado? [Resposta do aluno inaudível] >> O que é isso? >> [Aluno] Você não tem que crescer sempre. Exatamente. Você não tem que crescer sempre. E este é apenas um tipo de cobertura você está aqui as suas apostas, A idéia é que você não quer chamar realloc muito, porque ele tende a ser lenta. Toda vez que você perguntar o sistema operacional para a memória, como você vai ver em breve em um conjunto de problema futuro, tende a levar algum tempo. Assim, minimizando a quantidade de tempo, mesmo se você está perdendo um pouco de espaço, tende a ser uma coisa boa. Mas se lermos a parte final da GetString aqui - e, novamente, a compreensão cada linha, aqui, não é tão importante hoje - notar que, eventualmente, chama malloc novamente e aloca exatamente como muitos bytes como ele precisa para a cadeia e depois joga fora chamando o tampão livre excessivamente grande se realmente foi dobrado muitas vezes. Então, em suma, é assim que GetString vem trabalhando todo esse tempo. Tudo que faz é ler um personagem em um momento novo e de novo e de novo, e cada vez que precisa de um pouco de memória adicional, ele pede ao sistema operacional para ele chamando realloc. Alguma pergunta? Tudo bem. Um ataque. Agora que entendemos ponteiros ou pelo menos estão cada vez mais familiarizados com ponteiros, vamos considerar como o mundo inteiro começa a entrar em colapso se você não consegue se defender contra os usuários contraditório, pessoas que estão tentando invadir seu sistema, pessoas que estão tentando roubar o seu software, contornando alguns código de registro que eles poderiam ter que digitar dentro Dê uma olhada neste exemplo aqui, que é apenas o código C, que tem uma função principal na parte inferior que chama uma função foo. E o que é passar para foo? [Aluno] um único argumento. >> [Malan] Um argumento único. Então, argv [1], o que significa que a primeira palavra que o usuário digitou na linha de comando após a.out ou o que quer que o programa é chamado. Então foo no topo leva em um char *. Mas char * é exatamente o que? >> [Aluno] Uma seqüência. [Malan] Um fio, então não há nada de novo aqui. Essa seqüência é arbitrariamente sendo chamado de bar. Nesta linha aqui, char c [12], em uma espécie de semi-técnico Inglês, o que é essa linha está fazendo? [Estudante] Uma matriz de - Array >> de? >> [Aluno] Personagens. Personagens. >> Dê-me um conjunto de 12 caracteres. Assim, poderíamos chamar isso de um buffer. É tecnicamente chamado de c, mas um tampão na programação significa apenas um monte de espaço que você pode colocar algumas coisas dentro Então, por fim, memcpy que não usei antes, mas você provavelmente pode adivinhar o que ele faz. Ele copia memória. O que ele faz? Aparentemente, copia bar, a sua entrada, em c, mas apenas até o comprimento da barra. Mas há um bug aqui. >> [Aluno] Você precisa do caráter sizeof. Ok >>. Tecnicamente, devemos realmente fazer strlen (bar) * sizeof (char)). Isso é correto. Mas, no pior caso aqui, vamos supor que isso é - Okay. Depois, há dois erros. Então, sizeof (char)); Vamos fazer isso um pouco mais. Então, agora ainda há um bug, que é o que? >> [Resposta do aluno inaudível] Verifique se o quê? >> [Aluno] Verificar NULL. Nós geralmente deve ser a verificação de NULL porque as coisas ruins acontecem quando o ponteiro é NULL porque você pode acabar indo lá, e você não deve nunca estar indo para NULL por dereferencing com o operador estrela. Então, isso é bom. E o que mais estamos fazendo? Logicamente, há uma falha aqui também. [Aluno] Verifique se argc é> = a 2. Portanto, verifique se argc é> = 2. Ok, então há três bugs neste programa. Estamos verificando se o usuário realmente digitou alguma coisa em argv [1]. Bom. Então, qual é o bug terceiro? Sim. >> [Aluno] C pode não ser grande o suficiente. Bom. Nós verificado um cenário. Nós implicitamente verificado não copiar mais memória do que exceder o comprimento da barra. Então, se a string que o usuário digitou é de 10 caracteres, isto está dizendo apenas copiar 10 caracteres. E está tudo bem. Mas e se o usuário digitou uma palavra no prompt como uma palavra de 20 caracteres? Isto está dizendo cópia 20 caracteres de bar em que? C, também conhecida como o nosso buffer, o que significa que você acabou de escrever dados a 8 locais de bytes que você não possui, e você não possuí-los no sentido de que você nunca alocados eles. Portanto, este é o que é geralmente conhecido como o ataque de buffer overflow ou ataque estouro de buffer. E é um ataque no sentido de que se o usuário ou o programa que está chamando a sua função está fazendo isso de forma maliciosa, o que realmente acontece próximo pode ser realmente muito ruim. Então, vamos dar uma olhada nesta foto aqui. Esta imagem representa sua pilha de memória. Lembre-se que cada vez que você chamar uma função que você começa este quadro pouco sobre a pilha e depois outro e depois outro e outro. E, até agora, temos apenas um tipo de abstraídas estes como retângulos ou no conselho ou na tela aqui. Mas, se aumentar o zoom em um desses retângulos, quando você chamar uma função foo, verifica-se que há mais no interior da pilha de que o quadro em que retângulo que apenas x e y e a e b, como fizemos falando sobre swap. Acontece que há alguns detalhes de nível inferior, entre eles, endereço de retorno. Assim, verifica-se quando principal chama foo, principal tem de informar foo o endereço principal está na memória do computador porque de outro modo, assim que foo é feito de execução, tal como neste caso aqui, uma vez que você chegar a esta cinta fechado encaracolado no final de foo, como o diabo não foo sabe onde o controle do programa deve ir? Acontece que a resposta a essa pergunta é neste retângulo vermelho aqui. Isso representa um ponteiro, e cabe ao computador para armazenar temporariamente sobre a pilha de chamada o endereço da página, de modo que, logo que é feito foo execução, o computador sabe onde e qual linha principal para voltar. Quadro ponteiro salvo se relaciona de forma semelhante a esta. Char bar * aqui representa o que? Agora este segmento azul aqui é frame foo. O que é o bar? Bar é apenas o argumento para a função foo. Portanto, agora estamos de volta ao tipo de quadro familiar. Há mais coisas e mais distrações na tela, mas esse segmento de luz azul é apenas o que estamos desenhando no quadro-negro para algo como swap. Esse é o quadro para foo. E a única coisa em que agora é o bar, que é este parâmetro. Mas o que mais deve estar na pilha de acordo com este código aqui? [Aluno] char c [12]. >> [Malan] char c [12]. Nós também deve ver 12 quadrados de memória alocada para uma variável chamada c, e de fato temos que na tela. O topo há c [0], e em seguida o autor deste diagrama não se incomodou desenhando todas as praças, mas há de fato há 12 porque se você olhar no canto inferior direito, c [11], se você contar de 0 é o byte 12 tal. Mas aqui está o problema. Em que direção está crescendo c? Tipo de cima para baixo se ele começa no topo e cresce para baixo. Ele não se parece com nós mesmos deixamos pista muito aqui. Nós tipo de pintado nos em um canto, e que c [11] é até contra bar, que fica à direita contra o ponteiro de Moldura Salvo, que é até contra endereço de retorno. Não há mais espaço. Então, qual é a implicação então se você estragar e você tenta ler 20 bytes em um buffer de 12 bytes? Onde estão os 8 bytes adicionais indo? >> [Aluno] Inside - Dentro de tudo o resto, alguns dos quais é super importante. E a coisa mais importante, potencialmente, é a caixa vermelha lá, endereço de retorno, porque suponha que você acidentalmente ou adversarially substituir esses 4 bytes, que endereço de ponteiro, não apenas com o lixo, mas com um número que acontece para representar um endereço real na memória. Qual é a implicação, logicamente? >> [Aluno] Função vai voltar para um lugar diferente. Exatamente. Quando retorna foo e hits que chaveta, o programa vai continuar não voltar para a principal, que vai voltar a qualquer endereço em que é caixa vermelha. No caso de registro de software contornar, e se o endereço que está sendo devolvido a é a função que normalmente é chamado depois que você pagou para o software e inserido o seu código de registro? Você pode classificar de enganar o computador em não ir aqui, mas em vez de ir até aqui. Ou se você é realmente inteligente, um adversário pode realmente digitar no teclado, por exemplo, não uma palavra real, não 20 personagens, mas suponho que ele ou ela realmente tipos em alguns personagens que representam o código. E não vai ser de código C, que vai de fato ser os personagens que representam o código de máquina binária, 0s e 1s. Mas suponha que eles são espertos o suficiente para fazer isso, de alguma forma, colar no prompt de GetString algo que é essencialmente código compilado, e os últimos 4 bytes substituir esse endereço de retorno. E o endereço é que a entrada de fazer? É realmente armazena neste retângulo vermelho o endereço do primeiro byte do buffer. Então você tem que ser realmente inteligente, e isso é um monte de tentativa e erro para pessoas ruins lá fora, mas se você pode descobrir o quão grande é este buffer de tal forma que os bytes últimos na entrada que você fornecer para o programa acontecer de ser equivalente ao endereço do início de sua reserva, você pode fazer isso. Se dizemos normalmente Olá e \ 0, que é o que acaba no buffer. Mas se nós somos mais espertos e preenchemos o buffer com o que vamos chamar genericamente código de ataque - AAA, ataque, ataque, ataque - onde isso é apenas algo que faz algo ruim, o que acontece se você é realmente inteligente, você pode fazer isso. Na caixa vermelha aqui é uma seqüência de números - 80, C0, 35, 08. Note que que coincide com o número que está aqui em cima. É na ordem inversa, mas mais sobre isso em outro momento. Note que este endereço de retorno foi deliberadamente alterado para igualar o endereço aqui, não o endereço do principal. Então, se o cara mau é super inteligente, ele ou ela vai incluir nesse código de ataque algo como apagar todos os arquivos do usuário ou copiar as senhas ou criar uma conta de usuário que eu possa então fazer login para - nada. E isso é tanto o perigo e o poder de C. Porque você tem acesso a memória através de ponteiros e, portanto, você pode escrever o que quiser na memória de um computador, você pode fazer um computador fazer o que quiser simplesmente por ter que pular dentro do seu próprio espaço de memória. E assim até hoje tantos programas e tantos sites que estão comprometidas resumem-se a pessoas que tomam vantagem disso. E isso pode parecer um super ataque sofisticado, mas nem sempre é iniciado assim. A realidade é que o que as pessoas ruins normalmente fazer é, se é um programa em uma linha de comando ou um programa gráfico ou um site, você acabou de começar a fornecer um absurdo. Você digita uma palavra muito grande no campo de pesquisa e tecle Enter e esperar para ver se o site trava ou você esperar para ver se o programa se manifesta alguma mensagem de erro porque se você tiver sorte como o cara mau e você fornecer algumas informações louco que trava o programa, isso significa que o programador não antecipou seu mau comportamento, o que significa que você pode provavelmente com bastante esforço, estudo bastante e erro, descobrir como travar um ataque mais preciso. Assim como uma grande parte de segurança não é apenas evitar estes ataques completamente mas detectá-los e realmente olhar para os logs e ver o que as pessoas loucas entradas digitadas em seu site, o que termos de pesquisa digitados pessoas em seu site na esperança de transbordar alguns buffer. E isso tudo se resume a os princípios simples do que é uma matriz eo que isso significa para alocar e usar a memória. Relacionado com isso, então também é este. Vamos apenas olhar para dentro de um disco rígido novamente. Você se lembra de uma ou duas semanas atrás que quando você arrastar os arquivos para a lixeira ou lata de lixo, o que acontece? >> [Aluno] Nada. >> Absolutamente nada, certo? Eventualmente, se você executar pouco espaço em disco, Windows ou Mac OS vai começar a apagar arquivos para você. Mas se você arrastar alguma coisa lá dentro, que não é de todo segura. Todo o seu companheiro de quarto ou amigo ou membro da família tem a fazer é clicar duas vezes e, voilà, há todos os arquivos esboçado que você tentou excluir. A maioria de nós, pelo menos, saber que você tem com o botão direito ou clique e lixo o vazio ou algo assim. Mas, mesmo assim, que não chega a fazer o truque porque o que acontece quando você tem um arquivo em seu disco rígido que representa algum documento do Word ou algum JPEG, e isso representa o seu disco rígido, e digamos que esta faixa aqui representa o arquivo, e é composto de um monte de 0s e 1s. O que acontece quando você não só arrastar o arquivo para a lixeira ou lixeira mas também esvaziá-la? Espécie de nada. Não há absolutamente nada agora. Agora é só nada porque alguma coisa acontece na forma de tabela. Portanto, há uma espécie de banco de dados ou tabela dentro da memória de um computador que, essencialmente, tem uma coluna para arquivos dos nomes e uma coluna para arquivos 'localização, onde isso pode ser local de 123, apenas um número aleatório. Assim, poderíamos ter algo como x.jpeg e localização 123. O que acontece então quando você realmente esvaziar seu lixo? Que vai embora. Mas o que não vai embora é a 0s e 1s. Então, qual é então a conexão com pset4? Bem, com pset4, só porque temos acidentalmente apagados do cartão de memória flash compacto que tinha todas essas fotos ou apenas porque pela má sorte se corrompeu não significa que os 0s e 1s não ainda estão lá. Talvez alguns deles são perdidos porque algo foi corrompido no sentido de que alguns tornaram-se 0s e 1s 1s tornou 0s. Coisas ruins podem acontecer por causa do software de buggy ou hardware defeituoso. Mas muitos desses bits, talvez até 100% deles, ainda estão lá. É que o computador ou a câmera não sabe onde começou JPEG1 e onde JPEG2 iniciado. Mas se você, programador, sabe, com um pouco de habilidade onde os JPEGs são ou o que parece que você possa analisar o JPEG 0s e 1s e dizer, JPEG, você pode escrever um programa com essencialmente apenas um for ou while que recupera cada um desses arquivos. Assim, a lição, então, é para começar a forma segura de apagar seus arquivos se você gostaria de evitar este completamente. Sim. [Aluno] Como é que ele diz em seu computador que você tem mais memória do que você fez antes? Ter mais memória do que você fez antes - >> [aluno] Mais memória disponível. Oh. Boa pergunta. Então, por que depois de esvaziar a lixeira do seu computador não dizer que você tenha mais espaço livre do que você fez antes? Em poucas palavras, porque ele está mentindo. Mais tecnicamente, você tem mais espaço, porque agora você disse você pode colocar outras coisas em que o arquivo já foi. Mas isso não significa que os bits estão indo embora, e isso não significa que os bits estão a ser alteradas para todos 0s, por exemplo, para sua proteção. Então, por outro lado, se você seguramente apagar arquivos ou destruir fisicamente o dispositivo, que realmente é a única forma, por vezes, em torno disso. Então, por que não deixamos em que a nota semi-assustador, e vamos vê-lo na segunda-feira. [Aplausos] [CS50.TV]