Quão perigoso é acessar uma matriz fora dos limites?

221

Quão perigoso é acessar uma matriz fora de seus limites (em C)? Às vezes, pode acontecer que eu leio de fora da matriz (agora entendo que, então, acedo à memória usada por outras partes do meu programa ou mesmo além dela) ou estou tentando definir um valor para um índice fora da matriz. Às vezes, o programa trava, mas às vezes é executado, fornecendo apenas resultados inesperados.

Agora, o que eu gostaria de saber é, o quão perigoso isso é realmente? Se danificar meu programa, não é tão ruim. Se, por outro lado, quebrar algo fora do meu programa, porque de alguma forma consegui acessar alguma memória totalmente não relacionada, então é muito ruim, imagino. Eu li muito 'tudo pode acontecer', 'segmentação pode ser o problema menos ruim' , 'seu disco rígido pode ficar rosa e unicórnios podem estar cantando sob sua janela', o que é legal, mas qual é realmente o perigo?

Minhas perguntas:

  1. A leitura de valores de fora da matriz pode prejudicar algo além do meu programa? Eu imagino que apenas olhar as coisas não muda nada ou, por exemplo, alteraria o atributo 'última vez que foi aberto' de um arquivo que encontrei?
  2. A definição de valores fora da matriz pode prejudicar algo além do meu programa? A partir desta questão de estouro de pilha, concluo que é possível acessar qualquer local de memória, que não há garantia de segurança.
  3. Agora eu executo meus pequenos programas no XCode. Isso fornece alguma proteção extra ao redor do meu programa, onde ele não pode alcançar fora de sua própria memória? Isso pode prejudicar o XCode?
  4. Alguma recomendação sobre como executar meu código inerentemente incorreto?

Eu uso o OSX 10.7, Xcode 4.6.

ChrisD
fonte
Em geral, o sistema operacional protegerá a si próprio e a outros processos de sua infração. Não é algo em que você necessariamente queira confiar muito.
Hot Licks 26/03
7
Além disso, você nunca "alcançará" um arquivo no seu disco rígido ao acessar e indexar o array fora dos limites (em sua memória RAM).
precisa saber é o seguinte
1
Eu acredito que você está perguntando sobre matriz C, certo? então isso não tem nada a ver com o ObjC e realmente não se relaciona com nenhum IDE.
Bryan Chen
17
Aqui está o meu exemplo favorito de resultados estranhos (ele lida com a pilha, mas eu achei isso realmente esclarecedor ...).
phipsgabler
11
xkcd.com/371
Dan Is Fiddling Por Firelight

Respostas:

125

No que diz respeito ao padrão ISO C (a definição oficial do idioma), o acesso a uma matriz fora de seus limites tem " comportamento indefinido ". O significado literal disso é:

comportamento, mediante o uso de um construto de programa não transportável ou incorreto ou de dados errados, para os quais esta Norma Internacional não impõe requisitos

Uma nota não normativa expande sobre isso:

O possível comportamento indefinido varia de ignorar a situação completamente com resultados imprevisíveis, se comportar durante a tradução ou a execução do programa de maneira documentada característica do ambiente (com ou sem a emissão de uma mensagem de diagnóstico), até o término de uma tradução ou execução (com a emissão de uma mensagem de diagnóstico).

Então essa é a teoria. Qual é a realidade?

No "melhor" caso, você acessará uma parte da memória que pertence ao seu programa em execução no momento (o que pode causar um mau comportamento do programa) ou que não pertence ao seu programa em execução no momento (o que provavelmente fará com que o programa falha com algo como uma falha de segmentação). Ou você pode tentar gravar na memória que seu programa possui, mas isso é marcado como somente leitura; isso provavelmente também fará com que seu programa falhe.

Isso pressupõe que o seu programa esteja sendo executado em um sistema operacional que tenta proteger os processos em execução simultaneamente. Se o seu código estiver sendo executado no "bare metal", diga se faz parte de um kernel do SO ou de um sistema incorporado, então não existe essa proteção; seu código de mau comportamento é o que deveria fornecer essa proteção. Nesse caso, as possibilidades de danos são consideravelmente maiores, incluindo, em alguns casos, danos físicos ao hardware (ou a objetos ou pessoas próximas).

Mesmo em um ambiente protegido, nem sempre as proteções são 100%. Existem erros no sistema operacional que permitem que programas sem privilégios obtenham acesso root (administrativo), por exemplo. Mesmo com privilégios comuns de usuário, um programa com defeito pode consumir recursos excessivos (CPU, memória, disco), possivelmente derrubando todo o sistema. Muitos malwares (vírus, etc.) exploram a saturação de buffer para obter acesso não autorizado ao sistema.

(Um exemplo histórico: ouvi dizer que em alguns sistemas antigos com memória central , o acesso repetido a um único local de memória em um loop apertado pode literalmente fazer com que esse pedaço de memória derreta. Outras possibilidades incluem destruir uma tela CRT e mover a leitura / escreva a cabeça de uma unidade de disco com a frequência harmônica do gabinete da unidade, fazendo com que ela atravesse uma mesa e caia no chão.)

E sempre há Skynet com que se preocupar.

O ponto principal é o seguinte: se você pode escrever um programa para fazer algo ruim deliberadamente , é pelo menos teoricamente possível que um programa de buggy possa fazer a mesma coisa acidentalmente .

Na prática, é muito improvável que o seu programa de bugs rodando em um sistema MacOS X faça algo mais sério do que travar. Mas não é possível impedir completamente que o código de buggy faça coisas realmente ruins.

Keith Thompson
fonte
1
obrigado, eu realmente entendo isso. Mas isso imediatamente desencadeia uma pergunta de acompanhamento: o que um programador iniciante pode fazer para proteger seu computador de suas próprias criações possivelmente horríveis? Depois de testar um programa completamente, posso liberá-lo no mundo. Mas a primeira execução de teste deve ser um programa incorreto. Como vocês mantêm seus sistemas protegidos de si mesmos?
Chrisd
6
@ ChrisD: Nós tendemos a ter sorte. 8-)} Sério, a proteção no nível do SO é muito boa atualmente. Na pior das hipóteses, se eu escrever uma bomba de forquilha acidental , talvez seja necessário reiniciar para recuperar. Mas danos reais no sistema provavelmente não valem a pena se preocupar, desde que seu programa não esteja tentando fazer algo que possa ser perigoso. Se você estiver realmente preocupado, executar o programa em uma máquina virtual pode não ser uma má idéia.
Keith Thompson
1
Por outro lado, já vi muitas coisas estranhas acontecerem nos computadores que usei (arquivos corrompidos, erros irrecuperáveis ​​do sistema etc.), e não tenho idéia de quantas delas podem ter sido causadas por algum programa C exibindo o temido comportamento indefinido. (Até agora, nenhum demônios reais voaram para fora do meu nariz.)
Keith Thompson
1
obrigado por me ensinar garfo bombas - Eu tenho feito coisas perto de que, ao tentar recursão compreensão :)
Chrisd
2
scientificamerican.com/article/… então o fogo ainda é possível com a eletrônica moderna.
Mooing Duck
25

Em geral, os sistemas operacionais de hoje (os populares de qualquer maneira) executam todos os aplicativos em regiões de memória protegidas usando um gerenciador de memória virtual. Acontece que não é muito FÁCIL (digamos) simplesmente ler ou gravar em um local que exista no espaço REAL, fora da região (s) atribuída / alocada ao seu processo.

Respostas diretas:

1) A leitura quase nunca danifica diretamente outro processo, mas pode danificar indiretamente um processo se você ler um valor KEY usado para criptografar, descriptografar ou validar um programa / processo. A leitura fora dos limites pode ter efeitos adversos / inesperados no seu código se você estiver tomando decisões com base nos dados que está lendo

2) A única maneira de você realmente DANIFICAR algo gravando em um local acessível por um endereço de memória é se esse endereço de memória para o qual você está gravando for realmente um registro de hardware (um local que na verdade não é para armazenamento de dados, mas para controlar alguma peça de hardware) não é um local de RAM. De fato, você ainda normalmente não danifica algo, a menos que esteja escrevendo um local programável único que não seja regravável (ou algo dessa natureza).

3) Geralmente, a execução de dentro do depurador executa o código no modo de depuração. A execução no modo de depuração Tende a (mas nem sempre) interrompe seu código mais rapidamente quando você faz algo considerado fora da prática ou totalmente ilegal.

4) Nunca use macros, use estruturas de dados que já possuam verificação de limites de índice de matriz incorporada, etc.

ADICIONAL Devo acrescentar que as informações acima são realmente apenas para sistemas que usam um sistema operacional com janelas de proteção de memória. Se escrever código para um sistema incorporado ou mesmo para um sistema operacional (em tempo real ou outro) que não possua janelas de proteção de memória (ou janelas endereçadas virtuais), deve-se ter muito mais cuidado ao ler e gravar na memória. Também nesses casos, práticas de codificação SAFE e SECURE devem sempre ser empregadas para evitar problemas de segurança.

trumpetlicks
fonte
4
Práticas de codificação seguras e protegidas devem sempre ser empregadas.
Nik Bougalis
3
Eu sugeriria NÃO usar try / catch para código de buggy, a menos que você capturasse exceções muito específicas e soubesse se recuperar delas. Catch (...) é a pior coisa que você pode adicionar a um código de buggy.
31413 Eugene
1
@NikBougalis - Concordo plenamente, mas é ainda mais importante se o does not OS incluir espaços de proteção de memória / endereço virtual, ou há uma falta de OS :-)
trumpetlicks
@Eugene - eu nunca ter notado que, para ser um problema para mim, mas eu concordo com você, posso ter editado it out :-)
trumpetlicks
1) você quer dizer dano, porque eu estaria revelando algo que deveria ter ficado em segredo? 2) Não sei se entendi o que você quer dizer, mas acho que só estou acessando a RAM tentando acessar locais fora dos limites da matriz?
Chrisd
9

Não verificar os limites pode levar a efeitos colaterais feios, incluindo brechas na segurança. Um dos mais feios é a execução arbitrária de códigos . No exemplo clássico: se você possui uma matriz de tamanho fixo e usa strcpy()para colocar uma string fornecida pelo usuário, ela pode fornecer uma string que transborda o buffer e sobrescreve outros locais de memória, incluindo o endereço de código onde a CPU deve retornar quando sua função termina.

O que significa que seu usuário pode enviar uma string que fará com que seu programa chame essencialmente exec("/bin/sh"), o que o transformará em shell, executando o que ele quiser no seu sistema, incluindo a coleta de todos os dados e a transformação da máquina em um nó de botnet.

Veja Smashing The Stack For Fun And Profit para obter detalhes sobre como isso pode ser feito.

che
fonte
Eu sei que não deveria acessar os elementos da matriz além dos limites, obrigado por reforçar esse ponto. Mas a questão é, além de causar todo tipo de dano ao meu programa, posso inadvertidamente ultrapassar a memória do meu programa? E eu quero dizer no OSX.
27413 ChrisD
@ ChrisD: OS X é um sistema operacional moderno, portanto, fornece proteção total à memória. Por exemplo, você não deve se limitar ao que seu programa está autorizado a fazer. Isso não deve incluir mexer com outros processos (a menos que você esteja executando sob privilégios de root).
che
Eu prefiro dizer sob privilégios de anel 0, não de raiz.
Ruslan
Mais interessante é que os compiladores hiper-moderno pode decidir que se tentativas de código para ler foo[0]atravésfoo[len-1] depois de ter utilizado anteriormente um cheque de lencontra o comprimento da matriz, quer executar ou saltar um pedaço de código, o compilador deve se sentir livre para executar esse outro código incondicionalmente mesmo se o aplicativo possuir o armazenamento após a matriz e os efeitos da leitura, seria benigno, mas o efeito de invocar o outro código não seria.
Supercat
8

Você escreve:

Eu li muito 'tudo pode acontecer', 'segmentação pode ser o problema menos ruim', 'seu disco rígido pode ficar rosa e unicórnios podem estar cantando sob sua janela', o que é legal, mas qual é realmente o perigo?

Vamos colocar dessa maneira: carregar uma arma. Aponte para fora da janela sem nenhum objetivo específico e fogo. Qual é o perigo?

A questão é que você não sabe. Se o seu código sobrescrever algo que trava seu programa, você está bem, pois ele o interromperá em um estado definido. No entanto, se não travar, os problemas começam a surgir. Quais recursos estão sob controle do seu programa e o que isso pode fazer com eles? Quais recursos podem ficar sob controle do seu programa e o que isso pode fazer com eles? Conheço pelo menos um problema importante causado por esse estouro. O problema estava em uma função estatística aparentemente sem sentido que atrapalhou uma tabela de conversão não relacionada para um banco de dados de produção. O resultado foi uma limpeza muito cara depois. Na verdade, teria sido muito mais barato e mais fácil de lidar se esse problema tivesse formatado os discos rígidos ... com outras palavras: unicórnios rosa podem ser o seu menor problema.

A idéia de que seu sistema operacional o protegerá é otimista. Se possível, tente evitar escrever fora dos limites.

Udo Klein
fonte
ok, era exatamente disso que eu tinha medo. Vou "tentar evitar escrever fora dos limites", mas, vendo o que venho fazendo nos últimos meses, certamente o farei muito ainda. Como vocês se saíram tão bem em programação sem uma maneira segura de praticar?
26413 ChrisD
3
Quem disse que tudo o que já era seguro;)
Udo Klein
7

Não executar o programa como root ou qualquer outro usuário privilegiado não prejudicará o sistema, portanto, geralmente isso pode ser uma boa idéia.

Ao gravar dados em algum local aleatório da memória, você não "danifica" diretamente nenhum outro programa em execução no seu computador, pois cada processo é executado em seu próprio espaço de memória.

Se você tentar acessar qualquer memória não alocada para o processo, o sistema operacional interromperá a execução do programa com uma falha de segmentação.

Então, diretamente (sem executar como root e acessar diretamente arquivos como / dev / mem), não há perigo de que seu programa interfira com qualquer outro programa em execução no sistema operacional.

No entanto - e provavelmente é sobre isso que você já ouviu falar em termos de perigo - escrevendo dados aleatórios cegamente em locais aleatórios de memória por acidente, com certeza você pode danificar qualquer coisa que possa danificar.

Por exemplo, seu programa pode querer excluir um arquivo específico fornecido por um nome de arquivo armazenado em algum lugar do programa. Se, por acidente, você simplesmente substituir o local em que o nome do arquivo está armazenado, poderá excluir um arquivo muito diferente.

Mikyra
fonte
1
Se você estiver executando como root (ou algum outro usuário privilegiado), tenha cuidado. As saturações de buffer e de matriz são uma exploração de malware comum.
John Bode
na verdade, a conta que eu uso para toda a minha computação diária não é uma conta de administrador (eu uso a terminologia OSX, pois esse é o meu sistema). Você quer me dizer que não posso danificar algo tentando definir QUALQUER local da memória? Essa é realmente uma ótima notícia!
Chrisd
Como já mencionado anteriormente, o pior dano que você pode causar por acidente é o pior dano que você pode fazer como usuário. Se você quiser ter 100% de certeza de que não destrói nenhum dos seus dados, provavelmente poderá adicionar uma conta diferente ao seu computador e experimentar isso.
Mikyra
1
@mikyra: Isso é verdade apenas se os mecanismos de proteção do sistema forem 100% eficazes. A existência de malware sugere que você nem sempre pode confiar nisso. (Não quero sugerir que vale a pena se preocupar; é possível, mas improvável, que um programa possa explorar acidentalmente as mesmas falhas de segurança exploradas por malware).
Keith Thompson
1
A lista aqui inclui: Execução de código de fontes não confiáveis. Basta clicar no botão OK em qualquer pop-up do firewall sem sequer ler sobre o que se trata ou desligá-lo completamente se a conexão de rede desejada não puder ser estabelecida. Corrigindo binários com o mais novo hack de fontes duvidosas. Não é culpa do cofre se o proprietário convidar voluntariamente qualquer ladrão com os dois braços e portas fortificadas extra fortes abertas.
Mikyra 26/03
4

NSArrays no Objective-C recebem um bloco específico de memória. Exceder os limites da matriz significa que você acessaria a memória que não está atribuída à matriz. Isso significa:

  1. Essa memória pode ter qualquer valor. Não há como saber se os dados são válidos com base no seu tipo de dados.
  2. Essa memória pode conter informações confidenciais, como chaves privadas ou outras credenciais do usuário.
  3. O endereço da memória pode ser inválido ou protegido.
  4. A memória pode ter um valor alterado porque está sendo acessada por outro programa ou thread.
  5. Outras coisas usam o espaço de endereço da memória, como portas mapeadas na memória.
  6. Gravar dados em um endereço de memória desconhecido pode travar o programa, substituir o espaço da memória do SO e geralmente causar a implodição do sol.

Pelo aspecto do seu programa, você sempre quer saber quando o seu código está excedendo os limites de uma matriz. Isso pode levar à devolução de valores desconhecidos, causando uma falha no aplicativo ou fornecendo dados inválidos.

Richard Brown
fonte
NSArraystem exceções fora dos limites. E esta pergunta parece ser sobre o array C.
DrummerB
Eu realmente quis dizer matrizes C. Eu sei que há NSArray, mas por enquanto a maioria dos meus exercícios estão em C
Chrisd
4

Você pode tentar usar a memcheckferramenta no Valgrind ao testar seu código - ele não detectará violações de limites de matriz individuais dentro de um quadro de pilha, mas deve detectar muitos outros tipos de problemas de memória, incluindo aqueles que causariam sutis e mais amplos problemas fora do escopo de uma única função.

Do manual:

Memcheck é um detector de erro de memória. Ele pode detectar os seguintes problemas comuns nos programas C e C ++.

  • Acessando a memória, você não deve, por exemplo, ultrapassar e ultrapassar os blocos de pilha, ultrapassar a parte superior da pilha e acessar a memória depois que ela for liberada.
  • Usando valores indefinidos, ou seja, valores que não foram inicializados ou que foram derivados de outros valores indefinidos.
  • Libertação incorreta da memória heap, como blocos de heap com liberação dupla ou uso incompatível de malloc / new / new [] versus free / delete / delete []
  • Sobreposição de ponteiros src e dst em funções memcpy e relacionadas.
  • Perda de memória.

ETA: Embora, como diz a resposta de Kaz, não seja uma panacéia e nem sempre produza os resultados mais úteis, especialmente quando você está usando padrões de acesso interessantes .

Aesin
fonte
Eu suspeitaria que o Analyzer do XCode encontraria a maior parte disso? e minha pergunta não é tanto sobre como encontrar esses erros, mas se a execução de um programa que ainda possui esses erros é perigosa para a memória não alocada para o meu programa. Vou ter que executar o programa, a fim de ver os erros acontecendo
Chrisd
3

Se você fizer uma programação no nível de sistemas ou de sistemas embarcados, coisas muito ruins podem acontecer se você gravar em locais de memória aleatórios. Os sistemas mais antigos e muitos microcontroladores usam E / S mapeadas na memória; portanto, gravar em um local de memória que mapeia para um registro periférico pode causar estragos, especialmente se for feito de forma assíncrona.

Um exemplo é a programação da memória flash. O modo de programação nos chips de memória é ativado gravando uma sequência específica de valores em locais específicos dentro do intervalo de endereços do chip. Se outro processo fosse gravado em qualquer outro local no chip enquanto isso acontecesse, isso causaria falha no ciclo de programação.

Em alguns casos, o hardware envolve os endereços (os bits / bytes de endereço mais significativos são ignorados); portanto, a gravação em um endereço além do final do espaço de endereço físico resultará na gravação de dados no meio das coisas.

E, finalmente, CPUs mais antigas como o MC68000 podem bloquear até o ponto em que apenas uma redefinição de hardware pode fazê-las funcionar novamente. Não trabalhamos com eles há algumas décadas, mas acredito que foi quando ele encontrou um erro de barramento (memória inexistente) ao tentar lidar com uma exceção, ele simplesmente seria interrompido até que a redefinição do hardware fosse confirmada.

Minha maior recomendação é um plágio flagrante para um produto, mas não tenho interesse pessoal e não sou afiliado a eles de nenhuma maneira - mas com base em algumas décadas de programação C e sistemas embarcados onde a confiabilidade era crítica, o PC de Gimpel O Lint não apenas detecta esse tipo de erro, mas também cria um programador C / C ++ melhor, constantemente falando sobre maus hábitos.

Também recomendo a leitura do padrão de codificação MISRA C, se você conseguir uma cópia de alguém. Eu não vi nenhum recente, mas em alguns dias eles deram uma boa explicação de por que você não deveria / deveria fazer as coisas que eles cobrem.

Não sei quanto a você, mas, na segunda ou na terceira vez, recebo um coredump ou hangup de qualquer aplicativo, minha opinião sobre qualquer empresa que produziu diminui pela metade. Na quarta ou quinta vez, e o que quer que seja o pacote, torna-se uma prateleira e eu enfio uma estaca de madeira no centro do pacote / disco em que ele veio, apenas para garantir que ele nunca mais volte para me assombrar.

Dan Haynes
fonte
Dependendo do sistema, leituras fora da faixa também podem desencadear um comportamento imprevisível ou podem ser benignas, embora o comportamento benigno do hardware em cargas fora da faixa não implique um comportamento benigno do compilador.
Supercat
2

Eu estou trabalhando com um compilador para um chip DSP que deliberadamente gera código que acessa um após o final de uma matriz fora do código C que não!

Isso ocorre porque os loops são estruturados para que o final de uma iteração prefira alguns dados para a próxima iteração. Portanto, o dado pré-buscado no final da última iteração nunca é realmente usado.

Escrever código C assim invoca um comportamento indefinido, mas isso é apenas uma formalidade de um documento de normas que se preocupa com a portabilidade máxima.

Mais frequentemente, um programa que acessa fora dos limites não é otimizado de maneira inteligente. É simplesmente buggy. O código busca algum valor de lixo e, diferentemente dos loops otimizados do compilador mencionado acima, o código usa o valor em cálculos subsequentes, corrompendo-os.

Vale a pena capturar bugs como esse e, portanto, vale a pena tornar o comportamento indefinido apenas por esse motivo: para que o tempo de execução possa produzir uma mensagem de diagnóstico como "array overrun na linha 42 de main.c".

Em sistemas com memória virtual, uma matriz pode ser alocada de modo que o endereço a seguir esteja em uma área não mapeada da memória virtual. O acesso bombardeará o programa.

Como um aparte, observe que em C temos permissão para criar um ponteiro que esteja um após o final de uma matriz. E esse ponteiro deve comparar mais do que qualquer ponteiro ao interior de uma matriz. Isso significa que uma implementação C não pode colocar uma matriz no final da memória, onde o endereço mais um seria contornado e pareceria menor que outros endereços na matriz.

No entanto, o acesso a valores não inicializados ou fora dos limites às vezes é uma técnica de otimização válida, mesmo que não seja maximamente portátil. É por exemplo, por que a ferramenta Valgrind não relata acessos a dados não inicializados quando esses acessos acontecem, mas somente quando o valor é usado posteriormente de alguma maneira que possa afetar o resultado do programa. Você obtém um diagnóstico como "ramificação condicional em xxx: nnn depende de valor não inicializado" e às vezes pode ser difícil rastrear sua origem. Se todos esses acessos fossem capturados imediatamente, haveria muitos falsos positivos decorrentes do código otimizado do compilador, bem como do código otimizado manualmente.

Falando nisso, eu estava trabalhando com algum codec de um fornecedor que estava emitindo esses erros quando portado para Linux e executado no Valgrind. Mas o fornecedor me convenceu de que apenas vários bitso valor usado realmente veio da memória não inicializada e esses bits foram cuidadosamente evitados pela lógica. Somente os bons bits do valor estavam sendo usados ​​e o Valgrind não tem a capacidade de rastrear o bit individual. O material não inicializado veio da leitura de uma palavra após o final de um fluxo de bits de dados codificados, mas o código sabe quantos bits estão no fluxo e não usará mais bits do que realmente são. Como o acesso além do final da matriz de fluxo de bits não causa nenhum dano à arquitetura DSP (não há memória virtual após a matriz, nenhuma porta mapeada na memória e o endereço não quebra), é uma técnica de otimização válida.

"Comportamento indefinido" não significa muito, porque, de acordo com a ISO C, simplesmente incluir um cabeçalho que não está definido no padrão C ou chamar uma função que não está definida no próprio programa ou no padrão C são exemplos de indefinidos. comportamento. Comportamento indefinido não significa "não definido por ninguém no planeta" apenas "não definido pelo padrão ISO C". Mas, claro, o comportamento às vezes indefinido realmente é absolutamente não definido por qualquer pessoa.

Kaz
fonte
Além disso, desde que exista pelo menos um programa que uma implementação específica processe corretamente, mesmo que taxe nominalmente todos os limites de implementação fornecidos na Norma, essa implementação poderá se comportar arbitrariamente ao alimentar qualquer outro programa que esteja livre de violações de restrições e ainda esteja " compatível". Consequentemente, 99,999% dos programas C (qualquer coisa que não seja o "único programa" de uma plataforma) dependem de comportamentos nos quais o Padrão não impõe requisitos.
11126
1

Além do seu próprio programa, acho que você não quebrará nada, na pior das hipóteses você tentará ler ou escrever a partir de um endereço de memória que corresponda a uma página que o kernel não atribuiu aos seus processos, gerando a exceção adequada e ser morto (quero dizer, seu processo).

jbgs
fonte
3
..O que? Que tal substituir a memória em seu próprio processo usado para armazenar algumas variáveis ​​usadas mais tarde ... que agora mudaram misteriosamente seu valor! Esses bichos são muito divertidos de rastrear, garanto. Um segfault seria o melhor resultado. -1
Ed S.
2
Quero dizer, ele não vai "quebrar" outros processos, além de seu próprio programa;)
JBG
Eu realmente não me importo se eu quebrar meu próprio programa. Estou apenas aprendendo, o programa está obviamente errado de qualquer maneira, se eu acessar algo fora do limite da minha matriz. Eu apenas estou ficando cada vez mais preocupado com os riscos de quebrar alguma coisa durante a depuração minhas criações
Chrisd
O problema é: posso ter certeza de que, se tentar acessar a memória não atribuída a mim, que meu processo será morto? (estar em OSX)
Chrisd
3
Anos atrás, eu costumava ser um programador desajeitado em C. Eu acessei matrizes fora de seus limites centenas de vezes. Além do meu processo ser morto pelo sistema operacional, nada aconteceu.
JBG