0

私のコードでは、ジェネリック ポインターを使用した結果と思われる奇妙な動作が発生していますが、実際にはまったく不明です。次のようなかなり標準的な構造体があります。

typedef struct {
  char* name;
  PyAutoCFunc ac_func;
  void (*func)();
  PyAutoType type_id;
  int num_args;
  PyAutoType arg_types[MAX_ARG_NUM];
} func_entry;

static func_entry* func_entries;

ヒープに割り当てられたこれらの構造体要素の配列への静的ポインターを格納しています。この配列の新しい要素を作成して挿入する時点で、その値は次のようになります...

func_entry new_fe;
new_fe.name = malloc(strlen(name) + 1);
strcpy(new_fe.name, name);
... // Init rest of struct

func_entries[num_func_entries] = new_fe;
num_func_entries++;

func_entry* fe = &func_entries[num_func_entries-1];

printf("Setting function '%s' at address '%p', name address '%p'\n", name, fe, fe->name);

これは出力します。

>>> Setting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0xe40fe0'

fe->name のサイズと値に注意してください。次に、このポインターをハッシュテーブルに格納して、後で取得します。ハッシュテーブルでは、これは単純な void* として格納されます。後でハッシュテーブルからポインターを取得すると、奇妙なことが起こります。

func_entry* fe = PyAutoHashtable_Get(func_table, c_func_name);

printf("Getting function '%s' at address '%p', name address '%p'\n", c_func_name, fe, fe->name);

どの出力。

>>> Getting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0x6e6f74656c656b73'

fe のアドレスは明らかに問題なくハッシュテーブルに出入りしていますが、fe->name のサイズとアドレスが変更されています。さらに奇妙なことに、fe->name は以前とはサイズが異なり、さらには fe とはサイズが異なります。fe->name にアクセスしようとすると segfault が発生し、どうすればよいかわかりません。

興味深いことに、いくつかのリンクされたライブラリを含むアプリケーションでコードを使用すると、これが発生するようです。実行しているすべてのコードが 64 ビットであると確信しています。

別のアプリケーションで上記のコードを正常に実行し、fe->name (小さい方) の正しいポインターを取得しました。

また、Ubuntu Linux 64 ビットで実行し、gcc でコンパイルしています。

これは本当に私のC無知が輝くところですが、私はそれが何百万もの可能性があると想像しています. 誰でも光を当てることができますか?

4

3 に答える 3

1

name のそのアドレスは、メモリ破損の結果のようです。これは、ヒープから strdup によって返されるアドレスにはありそうにない、完全に整列されていません。

作成した構造の範囲外のようです。ヒープ上に作成されるとおっしゃいましたが、コードではおそらくスタック上に作成されているようです。これはすべて同じ関数で行われているわけではありませんよね? 関数の最初のブロックのコードは、後のブロックでコードを実行する前に存在していましたか? その関数を終了するとすぐに、その構造体へのポインターを保持していても、その構造体のメモリはなくなります。後で、ポインターをハッシュ テーブルから取り出したときに、メモリが上書きされ、そこに名前を付けるためのポインターがなくなりました。構造体へのポインターを渡す場合は、malloc を使用してそれらを動的に割り当てます。それらは、関数が終了するときではなく、free を使用して明示的に削除するまで存在します。

于 2012-04-17T20:33:41.717 に答える
0

確かに、何かがそのデータ構造を上書きしているように見えます。0x6e6f74656c656b73あなたが見ているポインタ値は確かに非常に疑わしいように見えます-それ"noteleks""skeleton"逆方向のASCIIです。おそらく、これはあなたのデータを何が上書きしているのかについての考えをあなたに与えるかもしれません。

于 2012-04-17T20:54:51.307 に答える
0

ポインターは、構造体へのポインターであろうと汎用ポインターであろうと、常に同じサイズです (昔は char *、ANSI 標準では void *)。

これは、構造、ポインターを理解できるように私が作成した簡単な例です (詳細ではありませんが、アイデアは理解できます)。

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

struct person {
    char *name;
    int age;
};

void print(void *);

int main()
{
    struct person *david;

    if ((david = (struct person *)malloc(sizeof(struct person))) != NULL) {
        david->name = strdup("David");
        david->age = 40;
        printf("sizeof david = %d, sizeof person = %d\n", sizeof david,
               sizeof(struct person));
        print((void *)david);
    }
}

void print(void *p)
{
    struct person *pp = (struct person *)p;
    printf("sizeof p = %d, sizeof pp = %d\n%s %d\n", sizeof p, sizeof pp,
           pp->name, pp->age);
}

出力

sizeof david = 8, sizeof person = 16
sizeof p = 8, sizeof pp = 8
David 40

それが役立つことを願っています。

于 2012-04-17T19:48:36.257 に答える