4

Solaris 5.8 マシンには、次のコードがあります。

[動かないコード]

char *buf;
char *dir;
size_t psize;

psize = (size_t) 1024;
dir = getcwd(buf, psize);

この UNIX マシンでは、上記の方法が機能せ、プログラムを実行しようとするとセグメンテーション エラーが発生します。dir に宣言した場合にのみ機能しますbuf:

【ワーキングコード】

char *dir;
char *buf;
...
dir = getcwd(buf, psize);

Mac OS X など、別の種類の Unix を使用している場合、コードの記述方法に関する非常に厳密なルールと思われるものは何も得られません。上記の例で何が起こっているのか、誰か説明できますか? ありがとう!

4

5 に答える 5

6

ここからgetcwd(3)です:

説明
     getcwd() 関数は、現在作業中の絶対パス名をコピーします。
     ディレクトリを buf が参照するメモリに格納し、buf へのポインタを返します。
     size 引数は、buf によって参照される配列のバイト単位のサイズです。

     buf が NULL の場合、必要に応じてパス名を格納するための領域が割り当てられます。
     このスペースは後で free(3) されるかもしれません。

つまり、tobufNULLwhen done を設定します。または、自分用にスペースを割り当てます (そこに 1K あることを伝えているため)。free(3)dirbufgetcwd(3)

編集:

少し整理すると、次のいずれかになります。

char *dir = getcwd( NULL, 0 );

if ( dir == NULL ) { /* handle error */ }
/* use dir */
free( dir );

また

char buf[1024]; /* or allocate it with malloc(3) */

if ( getcwd( buf, 1024 ) == NULL ) { /* handle error */ }

/* use buf, DO NOT free it if it's on the stack or static, 
   only if malloc-ed */
于 2010-04-12T00:46:06.867 に答える
4

POSIX では、最初の引数は、パス名が格納されているバッファーへのポインターである必要があります。Mac OS X、Linux、Solaris などに存在する一般的な拡張機能は、最初の引数が NULL の場合、getcwd()使用するバッファを割り当てるというものです。使い終わったら、malloc()これを使用して解放します。free()この拡張機能は POSIX で許可されていますが、必須ではないため、移植可能なコードではこれに依存しないでください。

あなたの場合、最初の引数として初期化されていない値をに渡していますgetcwd()。たまたま NULL に等しい場合は、バッファーが割り当てられます。それが他の無効なポインターである場合、セグメンテーション違反が発生する可能性があります。値は初期化されていないため、任意の値を持つことができ、宣言の順序に依存する可能性があります。によってバッファが割り当てられることを意図している場合getcwd()は、値 NULL を明示的に渡します。このために変数を宣言する必要はありません。ただし、より移植性の高い解決策は、この拡張機能に依存するのではなく、独自のバッファーへのポインターを渡すことです。

于 2010-04-12T01:05:04.587 に答える
3

ポインターを宣言しただけで、getcwd が書き込むためのメモリを割り当てていません。getcwd はメモリを割り当てません。自分で割り当てるには、malloc を呼び出す必要があります。

于 2010-04-12T00:45:09.573 に答える
2

ポインターを宣言する順序によって、ポインターがメモリ内のスタックに配置される順序が決まります。私の推測では、アドレスから始まるバッファ オーバーランがあり、例 1 ではbuf破棄dirされていますが、例 2 では破棄されていません。あなたは他のOSで、このバグを黙って防止しているか、何らかの方法で別の方法で処理している可能性があります。

于 2010-04-12T00:44:55.217 に答える
2

宣言の順序は問いません

char *getcwd(char *buf, size_t size);  

getcwd() 関数は、現在作業中の絶対パス名をコピーします。
長さ **size** の **buf** が指す配列へのディレクトリ。

buf使用する前にメモリを割り当てる必要があります。

buf = malloc(length * sizeof(char));

char *buf;が実行された後、bufガベージ値が含まれており、 getcwd()bu が指すメモリを変更しようとするとbuf、 が発生しSegmentation Faultます。

于 2010-04-12T00:45:10.077 に答える