2016-04-19 15 views
-2

これはなぜ機能しますか?malloc()に関する奇妙な動作

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main() 
{ 

    char * abc = malloc(1) + 4; //WRONG use of malloc. 
    char * xyz = "abc"; 
    strcpy(abc, xyz); //Should fail. 
    printf("%s\n", abc); //Prints abc 
} 

私はmalloc()の引数に1を渡しているので、十分なメモリがないためにstrcpyが失敗することが予想されます。代わりに、これは完璧にコンパイルされ、実行されます(Windowsの場合はlinuxではGCC、WindowsではdevC++)。

これは予想された動作ですか、それとも幸いな一致ですか?

これは良い習慣ではないと思われますが、なぜ機能するのですか?

malloc()の末尾に+4がないと、セグメンテーション違反が発生します。これは主に私が興味があることです。

+2

「仕事」という意味ではありません。 –

+0

あなたは精緻化できますか? – ale10ander

+4

未定義のビヘイビアーを呼び出すことは、常に悪い考えです。かつてコードが呼び出されたときにコードが特定の方法で動作する理由を調べることには役に立たない。なぜ1バイトを割り当てるのに十分なメモリがないのだろうと思っているのか分かりませんが、あなたは 'malloc'と友人についていくつか誤解を抱くかもしれません。 'void * 'の算術演算も定義されていません。 – Olaf

答えて

5

これは基本的にCにおけるポインタがローレベルと(典型的に)チェックされていないという事実の別の実証です。あなたは、 "十分な記憶を持っていないために失敗する"と思ったが、それについて考える:あなたは何が失敗すると思いますか? strcpy関数は、コピーしている文字列のための十分なスペースがあるかどうかを確かにチェックしません。そうする方法はありません。それが得られるのはポインタだけです。文字のコピーを開始し、実際にはセグメンテーション違反で成功するか死ぬかのどちらかです。 (ただし、ポイントはで、は「メモリ不足」で死ぬことはありません)

6

undefined behaviorです。 しないでください!

割り当てられた領域を超えてメモリの場所にアクセスしようとしています。したがって、メモリロケーションはが無効であり、無効なメモリにアクセスするとUBが呼び出されます。

FWIW、

  • がバウンド(無効)メモリ不足にアクセスするあなたを停止しないと

  • どちらも先のサイズにstrcpy()チェックを行うことをC標準であっ注目していますバッファはソース長と比較して

だから、このコード(何らかの形で)がコンパイルされます。あなたがそれを実行してUBにヒットすると、もう何も保証されません。

P.S - the only guaranteed thing here is undefined behavior.

+0

*未定義の動作で何が起こる可能性があるかについて[this](http://stackoverflow.com/a/25636788/841108)を参照してください。* –

+0

@BasileStarynkevitchリンクのおかげで、私の答えに埋め込まれました。 :) –

1

この動作に依存しないでください。このような動作に依存することが何年も発見されずに潜んでいて、ある日、ランタイムシステムのマイナーな調整が突然致命的な障害を引き起こすという点で、「積極的に」応答する回答者は正当です。

32ビットコンピュータの出現以来、—のほとんどが—のCランタイムライブラリでは、16バイト単位でヒープを管理するmalloc/freeを実装しているため、動作するようです。つまり、1から16までのパラメータを使用してmalloc()を呼び出すと、同じ割り当てが行われます。だからあなたはあなたが求めていたより少し多くのメモリを得て、それが実行できるようにします。

valgrindのようなツールは確かに問題を検出します。