0

私は学校の課題を持っていますが、理解できない一部を除いて、すべてがうまく機能しています。以下は、私の問題が発生しているコードのスニペットです。

    //something goes wrong here, wont copy over
    puts("bravo");
    //add to end of the list
    int size_list = sizeof(environ);
    //char** tmp_ptr = ( char** )calloc( size_list + 1, ( size_list + 1 ) * sizeof( char* ) );
    char** tmp_ptr = ( char** ) malloc ( ( size_list + 1 ) * sizeof( char* ) );
    int k;
    for ( k = 0; k < size_list; ++k )
    {
        tmp_ptr[k] = environ[k];
        //memcpy(tmp_ptr[k],environ[k],sizeof(environ[k]));
    }
    //char** tmp_ptr= (char**)realloc(*environ, size_list+2);
    environ = tmp_ptr;
    environ[size_list] = (char*)malloc(len_string+1);
    strcpy(environ[size_list],full_string);
    return 1;

「ブラボー」は無視してかまいません。問題が発生している場所を特定するのは私のためでした。Environ に変数の新しいリストを取得しようとしていますが、それを tmp_ptr に設定すると空になります。値がコピーされていることは確かですが、何が問題なのかわかりません。関数が終了すると tmp_ptr のデータは削除されますか? それは可能な説明ですか?メモリを適切に割り当ててコピーするにはどうすればよいですか。realloc を使用してみましたが、無効なポインター エラーが発生したため、calloc または malloc に依存しています。前もって感謝します。

4

2 に答える 2

4

environの長さは ではありませんsizeof(environ)。なぜなら、environは aだからですchar **(したがってsizeof(environ)、プラットフォームに応じて 4 または 8 になります)。あなたがしていることはenviron、最初のいくつかのエントリのみをコピーするため、事実上ほとんどを一掃することです.

のエントリ数を調べるにはenviron、次のようにします。

int cnt = 0;
char **envp = environ;
while(*envp++) cnt++;

また、このアプローチの問題にも注意する必要environがありNULLます。新しいエントリー。現在、コード (サイズが正しく計算されていれば) の後にエントリが追加され、プログラムには表示されません。NULLNULLNULL

補足:environこの方法をいじることは絶対にお勧めできません。代わりにgetenv/を使用してください。setenv環境を大量に設定する必要がある場合は、execve代わりに使用してみてください。(したがって、あなたの場合、環境setenv("varname", "varvalue", 1)に追加varname=varvalueするだけです(すでに設定されている場合は、既存のマッピングを置き換えることができますvarname)。

于 2012-09-25T01:31:48.633 に答える
3

environポインタです。つまりsizeof(environ)、その配列内の項目の数ではありません。むしろ、それはポインターのサイズであり、おそらくあなたの場合は 4 または 8 です。

environが (最後の 1 つがヌル ポインターである文字ポインターの配列) と同じ種類の構造である場合argv、NULL が見つかるまで配列を調べてそのサイズを決定する必要があります。

次のようなもの(テストされていませんが、アイデアは健全です):

char **envPtr = environ;
int size_list = 0;            // probably should be size_t
while (*envPtr != NULL) {
    envPtr++;
    size_list++;
}

この完全なプログラムで効果を確認できます (他のバグを回避するためにいくつかの変更を加えています)。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define full_string "xyzzy=plugh"
#define len_string strlen(full_string)

int main (int argc, char **argv) {
    int k, size_list = sizeof(environ);
    char **tmp_ptr = malloc ((size_list + 1) * sizeof ( char*));

    for (k = 0; k < size_list; ++k) printf ("[%s]\n", environ[k]);
    for (k = 0; k < size_list; ++k) tmp_ptr[k] = environ[k];
    tmp_ptr[size_list] = NULL;

    environ = tmp_ptr;
    environ[size_list] = malloc (len_string + 1);
    strcpy(environ[size_list],full_string);

    printf ("=====\n");
    for (k = 0; k <= size_list; ++k) printf ("[%s]\n", environ[k]);

    return 0;
}

4 バイトのポインターがあるため、これは 4 つの環境変数のみを出力します。

[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
=====
[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
[xyzzy=plugh]

環境のサイズを正しく判断するようにコードを変更します。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define full_string "xyzzy=plugh"
#define len_string strlen(full_string)

int main(int argc, char **argv) {
    int k, size_list = 0;
    char **envPtr = environ;
    while (*envPtr != NULL) {
        envPtr++;
        size_list++;
    }
    char **tmp_ptr = malloc ((size_list + 1) * sizeof (char*));

    for (k = 0; k < size_list; ++k) printf ("[%s]\n", environ[k]);
    for (k = 0; k < size_list; ++k) tmp_ptr[k] = environ[k];
    tmp_ptr[size_list] = NULL;

    environ = tmp_ptr;
    environ[size_list] = malloc (len_string + 1);
    strcpy(environ[size_list],full_string);

    printf ("=====\n");
    for (k = 0; k <= size_list; ++k) printf ("[%s]\n", environ[k]);

    return 0;
}

私に多くを与えます:

[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
[SHELL=/bin/bash]
[GTK_RC_FILES=/etc/gtk/gtkrc:/home/pax/.gtkrc-1.2-gnome2]
[WINDOWID=62914564]
[GNOME_KEYRING_CONTROL=/tmp/keyring-RADe9n]
[GTK_MODULES=canberra-gtk-module]
[USER=pax]
:
[XAUTHORITY=/var/run/gdm3/auth-for-pax-AO1dYc/database]
[_=./testprog]
=====
[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
[SHELL=/bin/bash]
[GTK_RC_FILES=/etc/gtk/gtkrc:/home/pax/.gtkrc-1.2-gnome2]
[WINDOWID=62914564]
[GNOME_KEYRING_CONTROL=/tmp/keyring-RADe9n]
[GTK_MODULES=canberra-gtk-module]
[USER=pax]
:
[XAUTHORITY=/var/run/gdm3/auth-for-pax-AO1dYc/database]
[_=./testprog]
[xyzzy=plugh]

価値のあるものとして、コードには次の問題がありました。

  • 明らかに、環境サイズの計算が正しくありません。
  • 戻り値のキャストmalloc- C では、コードの問題が隠される可能性があるため、これはお勧めできません。
  • 新しいリストの最後の要素を NULL に設定しない。
  • メモリ不足の状態をチェックしていません。

最後のものを除くこれらはすべて、上記の最終的なコード サンプルで修正されています。

于 2012-09-25T01:31:40.570 に答える