2012-04-17 10 views
0

実際のところ私は完全には不明ですが、一般的なポインタの使用に起因すると思われる私のコードでは、奇妙な動作が起こります。私はヒープに割り当てられているこれらの構造体要素の配列への静的ポインタを格納しています予期しないC構造体のポインタサイズの振る舞い

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の無知が輝いていますが、私はそれが100万点になると想像しています。誰も光を照らすことはできますか?

+1

fe-> nameを割り当てるコードを表示する必要があります。ここに示すように、初期化されていないようです。 –

+0

アドレスが変更されたように見える - 0xfe2d40!= 0x20049e0。私はMark Wilkinsに同意します - より多くのコード(特にPyAutoHastable_Getを参照する必要がありますが、その名前を設定するコードも疑わしい)です。 –

+0

fe->名前の割り当てに追加されました。実際にはコードの大部分であるので、私のハッシュテーブルの実装全体を投稿したくはありません(問題なく長時間使用していますが)。 feに対して同じ値を返すという事実は、私にとってはそれほど疑わしいものではありません。 –

答えて

0

ポインタは常に(ANSI規格では*、昔のcharの*無効。)その構造体へのポインタまたは汎用ポインタか同じ大きさ

は、ここでは、そのよう私はホイップ簡単な例です(ではないが、詳細ではなく、あなたのアイデアを得る。)の構造、ポインタを理解することができ

#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 

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

+2

ポインタがすべて同じサイズである必要はありません。現代のデスクトップOS上にある傾向がありますが、エキゾチックなハードウェアの場合、いくつかのポインタのサイズが異なる例があります。 –

+1

ねえ。答えをありがとうが、それは本当に多くの私の質問を助けることはありません。私はこの基本的なものにかなり精通しています。実際には、ポインタは時にはサイズが異なることがあります。まず第1に、32対64ビットがあり、第2に、いくつかのシステムでは、関数ポインタのサイズはさまざまです。http://c-faq.com/ptrs/generic.html –

+0

私のステートメントを明確にするために、同じマシン上のポインタサイズはすべて同じ。古いDOSボックスの場合に限り、遠くのポインタが近くにあり、遠いポインターがありましたが、それは違っていましたが、それは非標準です。 – g13n

1

名前のアドレスはメモリ破損の結果のようです。これは完全にアライメントされていません。ヒープからのストールによって返されるアドレスにはありそうもありません。

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

+0

ありがとう!私はそれが正確にスタックの問題ではないという気持ちを持っていますが、私はreallocを使っていて、メモリの動きはハッシュに格納されているポインタを無効にしていました! –

+0

Daniel、func_entry new_fe;の範囲を明確にすることができますか?これがfuncのローカル変数である場合、グローバルな配列がローカルの解放されたスタック変数を指していることは事実です。 mallocまたは新しい呼び出しを使用して、ヒープにfunc_entryを割り当てる必要があります。 – Tra5is

0

データ構造上に何かが書き込まれているかのように見えます。表示されているポインタ値0x6e6f74656c656b73は、実際には非常に疑わしいと思われます。"noteleks"のASCIIで、後方には"skeleton"です。おそらく、これはあなたのデータを上書きしているもののアイデアを与えるかもしれません。

+0

ありがとうございます。スケルトンは確かに私のコードベースによく現れる文字列です。私はどこかで深刻なメモリ破損があるかもしれないように思えます。 Eek。 –

関連する問題